Skip to main content
Glama
This connector has been deprecated

Duplicate listing. This connector has been replaced by ai.screwtape/screwtape.

Check an invoice for duplicates before the agent pays

check_duplicate_invoice

Spend gate for invoices: decides whether an agent may pay this invoice, with a signed receipt as proof. Same as judge with one duplicate check: it compares this invoice with the invoices this caller recorded earlier and also judges it. Call it before an agent pays or approves an invoice or payment instruction. Inputs: the judge inputs (task, agent_output as the invoice JSON, evidence, criteria, checks, mode, tags) plus duplicate {vendor_path, invoice_id_path, amount_path, currency_path?, date_path?, payee_account_path?, accept_payee_change?, window_days?, store?, retain_days?}. Returns the judge result plus duplicate.status (unique, duplicate, possible_duplicate, replay or not_checked). On duplicate or possible_duplicate, next_step.action is escalate: do not pay. Fingerprints are kept per caller; only keyed HMAC fingerprints are stored, and only when store is true. Cost: 1 call, the same as judge. First 3 calls per UTC day need no key (daily private IP namespace). Then use Authorization: Bearer , or a per-call payment in params._meta with no key (records are kept per payer; an unverified payment returns the payment requirements again). A free key covers 10 calls per UTC day (get_api_key or https://screwtape.ai/signup/). After the shared 3/day anonymous allowance (3/minute, global 2000/day), tools/call without a key or payment is HTTP 200 with isError true and the payment requirements in structuredContent.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "task": "<task>",
      "agent_output": "<agent_output>",
      "duplicate": "<duplicate>"
    },
    "name": "check_duplicate_invoice"
  }
}

Input Schema

NameRequiredDescriptionDefault
modeNoOptional. blocking (the default) is today's behaviour. advisory computes the same verdict, checks, next_step and receipt, then adds mode, decision_owner human, recommended_action (approve, review or return) and a notice. The receipt signs mode advisory as schema_version 5. Same price.
taskYesThe original instruction or question the agent was answering.
shareNoOptional. false keeps this call out of opt-in data sharing even when the key has sharing on. It cannot turn sharing on.
checksNoOptional. The worker runs each check. A failed check forces verdict fail. Types include url_contains, json_schema, equals, regex, numeric, required_fields, types, format, sum and duplicate. duplicate (at most 1) compares an invoice with ones this caller recorded earlier and stores keyed fingerprints only when store is true. At most 3 url_contains checks. Local checks run first; if one fails, no model is called and next_step says what to fix.
retainNoOptional. true stores this call for 24 hours; requires an API key. Default false stores nothing.
versionNoOptional version tag for that agent. At most 64 characters.
agent_idNoOptional tag for the agent making this call. 1 to 64 characters: letters, digits, and . _ : -. This is not the per-answer agent_id on a consensus answer.
criteriaNoOptional. Facts or terms the answer must contain, one per string.
evidenceNoOptional. Source passages the answer must be grounded in, one string per passage. Without evidence, grounding cannot be checked.
duplicateYesThe duplicate check: dot paths into agent_output for vendor, invoice id and amount, plus optional currency_path, date_path, payee_account_path, accept_payee_change, window_days, store and retain_days. payee_account_path remembers the vendor's bank or payee account; a change escalates with payee_account_changed. store true records this invoice's keyed fingerprints so later calls can match it.
agent_outputYesThe invoice or payment instruction the agent is about to pay, as a JSON string.

Output Schema

NameRequiredDescriptionDefault
modeNoPresent only when the call sent mode: advisory.
modelNo
scoreYesnull when no model gave a verdict (degraded).
checksNo
claimsNo
engineNogroq, workers_ai, deterministic, or demo. Also signed into the receipt.
noticeNoAdvisory only. Fixed text: the call does not approve, hold or release any payment.
reasonsYes
receiptNo
verdictYes
versionNoEchoed when the call sent a version tag.
agent_idNoEchoed when the call sent an agent_id tag.
degradedNo
duplicateNoPresent only when the call sent a duplicate check. status is unique, duplicate, possible_duplicate, replay or not_checked. Carries no invoice data.
next_stepNo
retentionNo
request_idYes
fail_closedNoPresent and true only when a finance check failed closed because the primary model was unavailable. Treat it as review.
verificationNo
decision_ownerNoAdvisory only. A person owns the decision.
receipt_reasonNo
recommended_actionNoAdvisory only, deterministic and not signed. Judge: next_step pass is approve, escalate is review, retry is return (send back to the agent). Consensus: risk low is approve, medium or high is review.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed11 schema fields changed
    • changedInput schema / properties / checks / description
      Previous value: -"Optional. The worker runs each check. A failed check forces verdict fail. Types: url_contains, json_schema, equals, regex, numeric, onchain, required_fields, types, format, sum, duplicate. duplicate (at most 1, API key only) compares an invoice with ones this key recorded earlier and stores keyed fingerprints only when store is true. At most 3 url_contains checks. Local checks run first; if one fails, no model is called and next_step says what to fix."New value: +"Optional. The worker runs each check. A failed check forces verdict fail. Types include url_contains, json_schema, equals, regex, numeric, required_fields, types, format, sum and duplicate. duplicate (at most 1) compares an invoice with ones this caller recorded earlier and stores keyed fingerprints only when store is true. At most 3 url_contains checks. Local checks run first; if one fails, no model is called and next_step says what to fix."
    • changedInput schema / properties / checks / items / oneOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "paths": {
      -        "items": {
      -          "description": "Dot path into the output JSON, at most 8 segments, e.g. invoice.total or items.0.id.",
      -          "maxLength": 128,
      -          "minLength": 1,
      -          "type": "string"
      -        },
      -        "maxItems": 50,
      -        "minItems": 1,
      -        "type": "array"
      -      },
      -      "type": {
      -        "const": "required_fields"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "paths"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "fields": {
      -        "additionalProperties": {
      -          "enum": [
      -            "string",
      -            "number",
      -            "integer",
      -            "boolean",
      -            "object",
      -            "array",
      -            "null"
      -          ]
      -        },
      -        "maxProperties": 50,
      -        "minProperties": 1,
      -        "type": "object"
      -      },
      -      "type": {
      -        "const": "types"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "fields"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "field": {
      -        "description": "Dot path into the output JSON, at most 8 segments, e.g. invoice.total or items.0.id.",
      -        "maxLength": 128,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "format": {
      -        "enum": [
      -          "email",
      -          "iso_date",
      -          "iso_datetime",
      -          "url",
      -          "uuid",
      -          "e164_phone",
      -          "currency_code",
      -          "integer_string"
      -        ]
      -      },
      -      "type": {
      -        "const": "format"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "field",
      -      "format"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "parts": {
      -        "items": {
      -          "description": "Dot path into the output JSON, at most 8 segments, e.g. invoice.total or items.0.id.",
      -          "maxLength": 128,
      -          "minLength": 1,
      -          "type": "string"
      -        },
      -        "maxItems": 20,
      -        "minItems": 1,
      -        "type": "array"
      -      },
      -      "tolerance": {
      -        "default": 0.0001,
      -        "maximum": 1000000,
      -        "minimum": 0,
      -        "type": "number"
      -      },
      -      "total": {
      -        "description": "Dot path into the output JSON, at most 8 segments, e.g. invoice.total or items.0.id.",
      -        "maxLength": 128,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "sum"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "parts",
      -      "total"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "Duplicate invoice check (needs an API key, at most 1 per call). Compares this invoice with ones the same key recorded earlier. Stores keyed HMAC fingerprints only, and only when store is true.",
      -    "properties": {
      -      "amount_path": {
      -        "description": "Dot path into the output JSON, at most 8 segments, e.g. invoice.total or items.0.id.",
      -        "maxLength": 128,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "currency_path": {
      -        "description": "Dot path into the output JSON, at most 8 segments, e.g. invoice.total or items.0.id.",
      -        "maxLength": 128,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "date_path": {
      -        "description": "Dot path to a YYYY-MM-DD invoice date. Enables the same vendor, amount and date rule.",
      -        "maxLength": 128,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "invoice_id_path": {
      -        "description": "Dot path into the output JSON, at most 8 segments, e.g. invoice.total or items.0.id.",
      -        "maxLength": 128,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "retain_days": {
      -        "default": 180,
      -        "maximum": 400,
      -        "minimum": 1,
      -        "type": "integer"
      -      },
      -      "store": {
      -        "default": false,
      -        "description": "Record this invoice's fingerprints so later calls can match it.",
      -        "type": "boolean"
      -      },
      -      "type": {
      -        "const": "duplicate"
      -      },
      -      "vendor_path": {
      -        "description": "Dot path into the output JSON, at most 8 segments, e.g. invoice.total or items.0.id.",
      -        "maxLength": 128,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "window_days": {
      -        "default": 3,
      -        "maximum": 30,
      -        "minimum": 0,
      -        "type": "integer"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "vendor_path",
      -      "invoice_id_path",
      -      "amount_path"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "description": "Existing types, unchanged: url_contains, json_schema, equals, regex, numeric, onchain.",
      -    "properties": {
      -      "type": {
      -        "enum": [
      -          "url_contains",
      -          "json_schema",
      -          "equals",
      -          "regex",
      -          "numeric",
      -          "onchain"
      -        ]
      -      }
      -    },
      -    "required": [
      -      "type"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "paths": {
      +        "items": {
      +          "description": "Dot path into the output JSON, at most 8 segments, e.g. invoice.total or items.0.id.",
      +          "maxLength": 128,
      +          "minLength": 1,
      +          "type": "string"
      +        },
      +        "maxItems": 50,
      +        "minItems": 1,
      +        "type": "array"
      +      },
      +      "type": {
      +        "const": "required_fields"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "paths"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "fields": {
      +        "additionalProperties": {
      +          "enum": [
      +            "string",
      +            "number",
      +            "integer",
      +            "boolean",
      +            "object",
      +            "array",
      +            "null"
      +          ]
      +        },
      +        "maxProperties": 50,
      +        "minProperties": 1,
      +        "type": "object"
      +      },
      +      "type": {
      +        "const": "types"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "fields"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "field": {
      +        "description": "Dot path into the output JSON, at most 8 segments, e.g. invoice.total or items.0.id.",
      +        "maxLength": 128,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "format": {
      +        "enum": [
      +          "email",
      +          "iso_date",
      +          "iso_datetime",
      +          "url",
      +          "uuid",
      +          "e164_phone",
      +          "currency_code",
      +          "integer_string"
      +        ]
      +      },
      +      "type": {
      +        "const": "format"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "field",
      +      "format"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "parts": {
      +        "items": {
      +          "description": "Dot path into the output JSON, at most 8 segments, e.g. invoice.total or items.0.id.",
      +          "maxLength": 128,
      +          "minLength": 1,
      +          "type": "string"
      +        },
      +        "maxItems": 20,
      +        "minItems": 1,
      +        "type": "array"
      +      },
      +      "tolerance": {
      +        "default": 0.0001,
      +        "maximum": 1000000,
      +        "minimum": 0,
      +        "type": "number"
      +      },
      +      "total": {
      +        "description": "Dot path into the output JSON, at most 8 segments, e.g. invoice.total or items.0.id.",
      +        "maxLength": 128,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "sum"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "parts",
      +      "total"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "Duplicate invoice check (needs an API key, at most 1 per call). Compares this invoice with ones the same key recorded earlier. Stores keyed HMAC fingerprints only, and only when store is true.",
      +    "properties": {
      +      "accept_payee_change": {
      +        "description": "Set after a person confirmed a changed payee account. With store true, the new account becomes the vendor's recorded account.",
      +        "type": "boolean"
      +      },
      +      "amount_path": {
      +        "description": "Dot path into the output JSON, at most 8 segments, e.g. invoice.total or items.0.id.",
      +        "maxLength": 128,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "currency_path": {
      +        "description": "Dot path into the output JSON, at most 8 segments, e.g. invoice.total or items.0.id.",
      +        "maxLength": 128,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "date_path": {
      +        "description": "Dot path to a YYYY-MM-DD invoice date. Enables the same vendor, amount and date rule. Without it, the same vendor, amount and currency within 30 days is possible_duplicate.",
      +        "maxLength": 128,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "invoice_id_path": {
      +        "description": "Dot path into the output JSON, at most 8 segments, e.g. invoice.total or items.0.id.",
      +        "maxLength": 128,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "payee_account_path": {
      +        "description": "Dot path to the bank or payee account (IBAN, account number, PayPal email). Remembered per vendor as a keyed HMAC; a different account escalates with payee_account_changed.",
      +        "maxLength": 128,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "retain_days": {
      +        "default": 180,
      +        "maximum": 400,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "store": {
      +        "default": false,
      +        "description": "Record this invoice's fingerprints so later calls can match it.",
      +        "type": "boolean"
      +      },
      +      "type": {
      +        "const": "duplicate"
      +      },
      +      "vendor_path": {
      +        "description": "Dot path into the output JSON, at most 8 segments, e.g. invoice.total or items.0.id.",
      +        "maxLength": 128,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "window_days": {
      +        "default": 3,
      +        "maximum": 30,
      +        "minimum": 0,
      +        "type": "integer"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "vendor_path",
      +      "invoice_id_path",
      +      "amount_path"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "description": "Other check types, unchanged from 1.0. See https://screwtape.ai/openapi.json.",
      +    "properties": {
      +      "type": {
      +        "enum": [
      +          "url_contains",
      +          "json_schema",
      +          "equals",
      +          "regex",
      +          "numeric",
      +          "onchain"
      +        ]
      +      }
      +    },
      +    "required": [
      +      "type"
      +    ],
      +    "type": "object"
      +  }
      +]
    • changedInput schema / properties / duplicate / description
      Previous value: -"The duplicate check: dot paths into agent_output for vendor, invoice id and amount, plus optional currency_path, date_path, window_days, store and retain_days. store true records this invoice's keyed fingerprints so later calls can match it."New value: +"The duplicate check: dot paths into agent_output for vendor, invoice id and amount, plus optional currency_path, date_path, payee_account_path, accept_payee_change, window_days, store and retain_days. payee_account_path remembers the vendor's bank or payee account; a change escalates with payee_account_changed. store true records this invoice's keyed fingerprints so later calls can match it."
    • addedInput schema / properties / duplicate / properties / accept_payee_change
      Added value: +{
      +  "description": "Set after a person confirmed a changed payee account. With store true, the new account becomes the vendor's recorded account.",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / duplicate / properties / date_path / description
      Previous value: -"Dot path to a YYYY-MM-DD invoice date. Enables the same vendor, amount and date rule."New value: +"Dot path to a YYYY-MM-DD invoice date. Enables the same vendor, amount and date rule. Without it, the same vendor, amount and currency within 30 days is possible_duplicate."
    • addedInput schema / properties / duplicate / properties / payee_account_path
      Added value: +{
      +  "description": "Dot path to the bank or payee account (IBAN, account number, PayPal email). Remembered per vendor as a keyed HMAC; a different account escalates with payee_account_changed.",
      +  "maxLength": 128,
      +  "minLength": 1,
      +  "type": "string"
      +}
    • changedOutput schema / properties / next_step / properties / error_type / enum
      Previous value: -[
      -  "none",
      -  "invalid_json",
      -  "not_an_object",
      -  "missing_required_field",
      -  "type_mismatch",
      -  "format_mismatch",
      -  "sum_mismatch",
      -  "check_failed",
      -  "external_check_failed",
      -  "duplicate_invoice",
      -  "possible_duplicate",
      -  "quality_issue",
      -  "contradicted_claims",
      -  "rejected",
      -  "low_confidence",
      -  "unverifiable",
      -  "false_consensus_risk",
      -  "primary_engine_unavailable"
      -]New value: +[
      +  "none",
      +  "invalid_json",
      +  "not_an_object",
      +  "missing_required_field",
      +  "type_mismatch",
      +  "format_mismatch",
      +  "sum_mismatch",
      +  "check_failed",
      +  "external_check_failed",
      +  "duplicate_invoice",
      +  "possible_duplicate",
      +  "payee_account_changed",
      +  "document_too_large",
      +  "quality_issue",
      +  "contradicted_claims",
      +  "rejected",
      +  "low_confidence",
      +  "unverifiable",
      +  "false_consensus_risk",
      +  "primary_engine_unavailable"
      +]
    • changedOutput schema / properties / receipt / properties / checks / description
      Previous value: -"Type, passed, and evidence_hash only. Fetched page text and chain responses are not stored."New value: +"Type, passed, and evidence_hash only. Fetched content is not stored."
    • changedOutput schema / properties / receipt / properties / model / description
      Previous value: -"Present only on schema 7 and 8: the model id the provider echoed back for this verdict, for example openai/gpt-oss-120b. Signed, so a changed model id fails verification."New value: +"Present only on schema 7 and 8: the model id the provider echoed back for this verdict. Signed, so a changed model id fails verification."
    • changedOutput schema / properties / receipt / properties / payment / description
      Previous value: -"x402 includes tx, network, and payer. Schema 4 free-key and prepaid payments are the label only, with no key_prefix. Schema 3 may include the key display prefix, not the secret. demo is the /try/ allowance."New value: +"How the call was paid. free-key and prepaid are the label only on schema 4; schema 3 may include the key display prefix, never the secret. demo is the /try/ allowance. Other paid calls may add tx, network and payer."
    • removedOutput schema / properties / receipt / properties / payment / properties / type / enum
      Removed value: -[
      -  "x402",
      -  "free-key",
      -  "prepaid",
      -  "demo"
      -]
  2. Changed10 schema fields changed
    • addedOutput schema / properties / degraded
      Added value: +{
      +  "type": "object"
      +}
    • addedOutput schema / properties / model
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • changedOutput schema / properties / receipt / properties / mode / description
      Previous value: -"Present only on schema 5: the call was advisory, so a person, not the API, owned the decision. Blocking receipts omit it."New value: +"Present only on schema 5 and 8: the call was advisory, so a person, not the API, owned the decision. Blocking receipts omit it."
    • addedOutput schema / properties / receipt / properties / model
      Added value: +{
      +  "description": "Present only on schema 7 and 8: the model id the provider echoed back for this verdict, for example openai/gpt-oss-120b. Signed, so a changed model id fails verification.",
      +  "type": "string"
      +}
    • changedOutput schema / properties / receipt / properties / schema_version / description
      Previous value: -"5 is schema 4 plus a signed mode advisory, minted only for mode: advisory calls. 4 omits key_prefix from payment so a published receipt verifies without key info. 3 adds verification, engine, checks (type, passed, and evidence_hash only), and a claims count, and may include key_prefix. 2 can carry agent_id and version. Older receipts omit this field and still verify."New value: +"7 is schema 4 plus a signed model id, and 8 is schema 5 plus a signed model id: minted when a model gave the verdict. 5 is schema 4 plus a signed mode advisory, minted only for mode: advisory calls. 4 omits key_prefix from payment so a published receipt verifies without key info. 3 adds verification, engine, checks (type, passed, and evidence_hash only), and a claims count, and may include key_prefix. 2 can carry agent_id and version. Older receipts omit this field and still verify."
    • changedOutput schema / properties / receipt / properties / schema_version / enum
      Previous value: -[
      -  2,
      -  3,
      -  4,
      -  5
      -]New value: +[
      +  2,
      +  3,
      +  4,
      +  5,
      +  7,
      +  8
      +]
    • changedOutput schema / properties / receipt / type
      Previous value: -"object"New value: +[
      +  "object",
      +  "null"
      +]
    • addedOutput schema / properties / receipt_reason
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / score / description
      Added value: +"null when no model gave a verdict (degraded)."
    • changedOutput schema / properties / score / type
      Previous value: -"number"New value: +[
      +  "number",
      +  "null"
      +]
  3. Changed3 schema fields changed
    • changedOutput schema / properties / engine / description
      Previous value: -"groq, workers_ai, deterministic, or demo."New value: +"groq, workers_ai, deterministic, or demo. Also signed into the receipt."
    • addedOutput schema / properties / fail_closed
      Added value: +{
      +  "description": "Present and true only when a finance check failed closed because the primary model was unavailable. Treat it as review.",
      +  "type": "boolean"
      +}
    • changedOutput schema / properties / next_step / properties / error_type / enum
      Previous value: -[
      -  "none",
      -  "invalid_json",
      -  "not_an_object",
      -  "missing_required_field",
      -  "type_mismatch",
      -  "format_mismatch",
      -  "sum_mismatch",
      -  "check_failed",
      -  "external_check_failed",
      -  "duplicate_invoice",
      -  "possible_duplicate",
      -  "quality_issue",
      -  "contradicted_claims",
      -  "rejected",
      -  "low_confidence",
      -  "unverifiable",
      -  "false_consensus_risk"
      -]New value: +[
      +  "none",
      +  "invalid_json",
      +  "not_an_object",
      +  "missing_required_field",
      +  "type_mismatch",
      +  "format_mismatch",
      +  "sum_mismatch",
      +  "check_failed",
      +  "external_check_failed",
      +  "duplicate_invoice",
      +  "possible_duplicate",
      +  "quality_issue",
      +  "contradicted_claims",
      +  "rejected",
      +  "low_confidence",
      +  "unverifiable",
      +  "false_consensus_risk",
      +  "primary_engine_unavailable"
      +]
  4. Added

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag a non-read-only, non-idempotent, open-world call, and the description adds substantial context on top: HMAC fingerprints kept per caller, storage only when store is true, retain_days retention, and the payee-account escalation path. It also discloses auth mechanics and limits (3 free calls per UTC day, Bearer key, 10/day free key, 3/minute, 2000/day global, and the HTTP 200 + isError true payment-required shape), which an agent cannot infer from annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded and every technical detail is relevant, but the description is a dense run-on that mixes the core contract with a long pricing/rate-limit block (anonymous allowance, free key, per-call payment, HTTP status behavior). That billing boilerplate dominates the second half and would read better as separated or condensed sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 11-parameter, nested-schema tool with an output schema, the description covers the call trigger, the required inputs, the duplicate-specific options, the result statuses, and the escalation action. Nothing an agent needs to invoke it correctly or interpret the verdict is missing, and return-value detail is delegated to the output schema as expected.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline would be 3, but the description goes further by grouping the parameters into "the judge inputs (task, agent_output as the invoice JSON, evidence, criteria, checks, mode, tags) plus duplicate {...}" and enumerating the duplicate sub-fields. It also explains the meaning of outcomes (duplicate.status values unique/duplicate/possible_duplicate/replay/not_checked), which adds semantic value over the schema's per-field text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

"Spend gate for invoices: decides whether an agent may pay this invoice, with a signed receipt as proof" states a specific verb (decides/checks), a specific resource (invoice), and the output (verdict + signed receipt). It also explicitly positions itself against the sibling judge tool ("Same as judge with one duplicate check"), so an agent can pick between them without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives an explicit call trigger ("Call it before an agent pays or approves an invoice or payment instruction") and an explicit stop rule on the outcome ("On duplicate or possible_duplicate, next_step.action is escalate: do not pay"). It also states the relationship to the alternative (judge) and the difference in cost ("1 call, the same as judge"), which is enough to route correctly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources