Duplicate invoices
The same invoice sent twice, or resent with a new number. Stored only as keyed fingerprints, never the invoice itself.

Payment checks for AI agents
Before money moves, Screwtape checks the invoice your agent wants to pay: the math, the purchase order, duplicates and your payment rules. You get approve, block, or send to a person, with a signed receipt your auditor can verify.
Works with the agent you already run. One API call before the payment step.
Screwtape.ai is this API. An unrelated research paper is also called Screwtape.
How it works
It sends the invoice, the PO or ledger it relied on, and its decision to approve.
Line math and totals, a match against the PO or ledger it sent, a duplicate check against invoices you already recorded, required fields, and, on team plans, your rules: amount caps, approved vendors, second approval.
On team plans, approve comes with a 15-minute, single-use pass token tied to that exact invoice, amount and vendor. Block or review comes with the reasons. Every decision gets a signed receipt.
What it looks for
The same invoice sent twice, or resent with a new number. Stored only as keyed fingerprints, never the invoice itself.
Line totals, tax and the invoice total that don't add up, or don't match the purchase order.
Over the cap, an unknown vendor, a missing field, or a payment that needs a second approver.
Signed receipts that show what was checked, when, and the decision. Export them for your auditor.
Screwtape flags problems for your agent and your team to act on. Verdicts are produced by AI models and automated checks. They can be wrong, and they do not guarantee that every error or fraudulent invoice is caught. Keep a person in charge of payments.
Under the hood
POST /v1/judge returns pass, fail, or retry on any agent output against your task, evidence and criteria.
POST /v1/consensus scores 2 to 16 agent answers and flags agreement that looks copied or thin. See the false-consensus article.
Demo
There is no unpaid judge on the public internet. The verdict on the right is an example response shape from the string-check fallback used when no model key is set. The button sends that same JSON to POST /v1/judge with no key.
{
"task": "State the crew size and launch site.",
"agent_output": "The crew size was 4. The mission launched from Cape Canaveral.",
"evidence": [
"The mission launched on 2024-03-01 from Cape Canaveral.",
"The crew size was 4."
],
"criteria": [
"crew size",
"Cape Canaveral"
]
}
Example response shape. The verdict, score, reasons, and engine value deterministic are what this input returns when no model key is set. request_id is the placeholder example-request-id. With a model key, engine is groq, then workers_ai if Groq is unavailable. String checks are the last fallback. A usable model reply appends “Judged by the configured LLM.”
{
"verdict": "pass",
"score": 0.9,
"reasons": [
"2 of 2 claims are grounded in the supplied evidence.",
"2 of 2 criteria matched the output.",
"Deterministic string checks only. No model was called."
],
"engine": "deterministic",
"verification": "heuristic",
"claims": [
{
"text": "The crew size was 4.",
"status": "supported"
},
{
"text": "The mission launched from Cape Canaveral.",
"status": "supported"
}
],
"checks": [],
"retention": {
"retained": false
},
"request_id": "example-request-id"
}
Example response shape. The agreement score, risk, reasons, clusters, and engine value deterministic are what this input returns when no model key is set. request_id is the placeholder example-request-id. With a model key, engine is groq, then workers_ai if Groq is unavailable. Clusters stay overlap grouping only, and a usable model reply appends “Scored by the configured LLM. Clusters below are overlap grouping only, not a judgment that the answer is right.”
curl -s https://screwtape.ai/v1/consensus \
-H "Authorization: Bearer $SCREWTAPE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"task":"State the crew size.","answers":[{"agent_id":"alpha","output":"The crew size was 4."},{"agent_id":"beta","output":"The crew size was 4."},{"agent_id":"gamma","output":"The crew size was 4."}]}'
{
"consensus_answer": "The crew size was 4.",
"agreement_score": 1,
"false_consensus_risk": "high",
"reasons": [
"Answers are nearly verbatim. High agreement may be copied rather than independent.",
"Agreement is token overlap, not a model judgment. Clusters are overlap grouping only."
],
"clusters": [
{
"size": 3,
"agent_ids": [
"alpha",
"beta",
"gamma"
],
"representative": "The crew size was 4.",
"role": "clustering"
}
],
"engine": "deterministic",
"verification": "heuristic",
"unsupported_agreement": false,
"retention": {
"retained": false
},
"request_id": "example-request-id"
}
Pricing
These figures are the same ones published at pricing.json.
Start here
$0
100 calls per UTC day, per key. POST /v1/signup. Email and name are optional.
Card
$5
$5 · 1,000 calls · 30 days · one per customer.
Card only. One per customer.
Card
$40
10,000 prepaid calls for $40 USD.
Pay by card through PayPal.
Card
$175
50,000 prepaid calls for $175 USD.
Pay by card through PayPal.
Monthly or annual. Annual is two months free. Billed through PayPal. No API key needed: enter an email (or use your PayPal one), and your team's key is created when PayPal confirms and shown to you once. Already have a key? Link it in the form. See how plans work.
For a finance team
$199 / mo
or $1,990 / yr
For controls and audit
$399 / mo
or $3,990 / yr
Pay by card through PayPal.
Prices in USD. Packs are one-time purchases and do not renew. For business use, under the Terms of Service.
Screwtape runs as a separate service from your agent, with its own prompt and checks, and it is not paid more when your agent passes. Every verdict comes with a signed receipt you can verify yourself. The receipt proves what was checked, when, and the verdict that was returned.
Trust
Judged text is not stored unless you set retain to true with an API key. The privacy policy lists every practice. Unlisted practices are not done.
Receipts are kept for audit; judged content is not stored by default. An opt-in row lasts 24 hours by default. DELETE /v1/keys/me deletes the key and the rows tied to it. A call without an API key cannot turn retention on.
Terms of Service, a Data Processing Addendum with EU Standard Contractual Clauses, and the subprocessor list on the trust page.
MCP at /mcp, OpenAPI 3.1 and an A2A agent card. No invented ratings or customer counts.
For developers and agents
An agent calls POST /v1/signup or the MCP tool get_api_key. No one has to approve the key.
Start on the free tier. When you need more, buy a prepaid pack by card. Details are on the pricing page.
Streamable HTTP MCP at /mcp. Copy-paste pages for CrewAI, LangGraph and AutoGen.
OpenAPI 3.1, an A2A agent card and llms.txt.
No SDK. When a step finishes, POST the output. Samples below use https://screwtape.ai and SCREWTAPE_API_KEY from the environment.
curl -s https://screwtape.ai/v1/judge \
-H "Authorization: Bearer $SCREWTAPE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"task":"State the crew size and launch site.","agent_output":"The crew size was 4. The mission launched from Cape Canaveral.","evidence":["The mission launched on 2024-03-01 from Cape Canaveral.","The crew size was 4."],"criteria":["crew size","Cape Canaveral"]}'import json
import os
import urllib.request
key = os.environ["SCREWTAPE_API_KEY"]
payload = {
"task": "State the crew size and launch site.",
"agent_output": "The crew size was 4. The mission launched from Cape Canaveral.",
}
request = urllib.request.Request(
"https://screwtape.ai/v1/judge",
data=json.dumps(payload).encode(),
headers={
"Authorization": "Bearer " + key,
"Content-Type": "application/json",
},
method="POST",
)
print(urllib.request.urlopen(request).read().decode())
const key = process.env.SCREWTAPE_API_KEY;
const payload = {
task: "State the crew size and launch site.",
agent_output: "The crew size was 4. The mission launched from Cape Canaveral.",
};
const response = await fetch("https://screwtape.ai/v1/judge", {
method: "POST",
headers: {
Authorization: `Bearer ${key}`,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
console.log(await response.json());
{
"mcpServers": {
"screwtape": {
"url": "https://screwtape.ai/mcp",
"headers": {
"Authorization": "Bearer ${env:SCREWTAPE_API_KEY}"
}
}
}
}class ScrewtapeJudgeTool(BaseTool):
name: str = "screwtape_judge"
description: str = "Judge an agent output. Returns JSON with verdict, score, and reasons."
args_schema: type[BaseModel] = JudgeInput
def _run(self, task: str, agent_output: str) -> str:
return json.dumps(screwtape_post("/v1/judge", {"task": task, "agent_output": agent_output}))
def judge(state: State) -> dict:
payload = {"task": state["task"], "agent_output": state["agent_output"]}
return {"verdict": screwtape_post("/v1/judge", payload)}
graph = StateGraph(State)
graph.add_node("judge", judge)
graph.set_entry_point("judge")
graph.add_edge("judge", END)
app = graph.compile()
Full CrewAI, LangGraph, AutoGen, and curl files are on the integrations pages. These tabs use the same endpoints and the same Bearer header. There is no separate SDK.
| Price per call | $0.005 USD for POST /v1/judge and POST /v1/consensus. |
|---|---|
| Free tier | 100 calls per UTC day per key. FREE_DAILY_LIMIT defaults to 100. |
| Prepaid packs | Starter $40 USD for 10000 calls; Builder $175 USD for 50000 calls. Pay by card through PayPal. |
| Trial pack | Trial $5 USD for 1000 calls, valid 30 days, one per customer. Card only through PayPal, POST /v1/packs/checkout with pack trial. Up to 24,000 characters in total per call (task, agent_output and evidence combined; agent_output alone is at most 16,000 on every plan). |
| Auth | Authorization: Bearer API key. |
| Endpoints | POST /v1/judge, POST /v1/consensus, and POST /v1/signup. |
| MCP URL | https://screwtape.ai/mcp |
| Input limits | total per call of task, agent_output or answers, evidence and criteria 24000 characters (12000 on a free key with no prepaid calls); task 8000 characters; agent_output and consensus output 16000 characters; evidence up to 20 items of 4000 characters; criteria up to 20 items of 500 characters; answers 2 to 16; agent_id 80 characters; request body 100000 bytes; signup name 80 characters; signup email 200 characters. |
| Data retention | Receipts are kept for audit; judged content is not stored by default. Judged content is not stored unless retain is true and the caller uses an API key. A call without an API key cannot turn retention on. The default is 24 hours. A key can set retention_days to 0 or 1 (30, 90 or 365 on a subscription plan). Day 0 stores neither content nor receipts. DELETE /v1/keys/me deletes the key, its retained rows, and its receipt log. Opt-in data sharing is off by default. A key that turns it on stores redacted samples of its calls for 90 days, and turning it off deletes them. |
| Independence | Screwtape runs as a separate service from your agent, with its own prompt and checks, and it is not paid more when your agent passes. A successful judge or consensus call includes a signed receipt when receipt signing is configured. The receipt proves what was checked, when, and the verdict. It does not prove the verdict is correct. POST /v1/receipts/verify checks that receipt. |
| Status | GET /v1/status, /status.json, and /status/ report measured response time for judge and consensus. uptime is successful calls divided by successes, 5xx responses, and timeouts. It is null when that denominator is 0. Unpaid 402 responses are a separate count and are not failures. 401 and 429 responses are not failures either. |
FAQ
POST /v1/judge returns pass, fail, or retry, a score, reasons, and a request id. POST /v1/consensus scores 2 to 16 answers and returns an agreement score, false-consensus risk, clusters, and a request id.
POST /v1/signup, or the MCP tool get_api_key, takes an optional email, an optional name, and a proof-of-work nonce. The form at /signup solves that proof in the browser. The key is shown once. Only a SHA-256 hash is stored. The free tier is 100 calls per UTC day.
The Trial pack is $5 USD for 1,000 calls, valid 30 days, one per customer, by card only. Starter is $40 USD for 10000 calls. Builder is $175 USD for 50000 calls. Pay by card through PayPal.
Receipts are kept for audit; judged content is not stored by default. Judged content is not stored unless you set retain to true and authenticate with an API key. A call without an API key cannot turn retention on. A retained row lasts 24 hours. DELETE /v1/keys/me deletes the key and its retained rows. Opt-in data sharing is off by default. When a key turns it on, its calls are stored after automatic redaction for 90 days, and turning it off deletes them.
MCP streamable HTTP at /mcp, OpenAPI 3.1 at /openapi.json, and A2A JSON-RPC at /a2a. message/send maps to a judge verdict.
GET /v1/health and GET /health return the same liveness body. We aim for 99.9% monthly availability; that is a target, not a promise or a contractual SLA. Measured uptime is at /status.json.
Create a free key in the browser, or send the agent to POST /v1/signup.