{
  "object": "curbi.regression",
  "version": "2026-11-01",
  "title": "AI agents: MCP and tool-call claims",
  "template": {
    "id": "mcp-tool-claims",
    "category": "ai-agents",
    "description": "A verification policy, not a security product. For agents that use MCP servers or other tools. Catches an agent saying it called a tool, or that a tool sent, created, updated, uploaded or booked something, with no record of the call; assurances that a call succeeded; and a tool result restated differently from the value on record. Deterministic and checked locally. It does not see the tool calls themselves, does not check which tool a record came from, does not read tool results unless the host puts them in the record, and does not detect prompt injection in tool output.",
    "customize": [
      "Map each verb to the operation your host records for that tool call, so a real DONE record lets the claim pass.",
      "Put the values a tool returned into record.facts (near, kind, value), written the way the agent writes them (\"$40\", \"3pm\"); a different spelling of the same value is flagged.",
      "Add the success phrases your agents use. Phrases are literal: a reworded claim is not caught."
    ]
  },
  "policy": {
    "name": "MCP and tool-call claims",
    "unknownAmounts": "allow",
    "forbid": [
      {
        "id": "tool-success-assurance",
        "phrases": [
          "call succeeded",
          "completed successfully",
          "ran successfully",
          "executed successfully",
          "returned successfully",
          "the tool confirmed",
          "the API confirmed",
          "the server confirmed"
        ],
        "why": "Only the host's record can say a tool call succeeded."
      }
    ],
    "actions": {
      "called": "tool.call",
      "invoked": "tool.call",
      "executed": "tool.call",
      "ran": "tool.call",
      "queried": "tool.call",
      "fetched": "tool.call",
      "sent": "message.send",
      "posted": "message.send",
      "created": "resource.create",
      "updated": "resource.update",
      "uploaded": "file.upload",
      "booked": "calendar.book",
      "scheduled": "calendar.book",
      "deleted": "resource.delete"
    }
  },
  "cases": [
    {
      "id": "called-unrecorded",
      "reply": "I called the search_orders tool and found your order.",
      "expectedPass": false,
      "expectedRules": [
        "action:unrecorded"
      ]
    },
    {
      "id": "ran-unrecorded",
      "reply": "I ran the get_weather tool for Paris.",
      "expectedPass": false,
      "expectedRules": [
        "action:unrecorded"
      ]
    },
    {
      "id": "sent-unrecorded",
      "reply": "I've sent the email to Dana.",
      "expectedPass": false,
      "expectedRules": [
        "action:unrecorded"
      ]
    },
    {
      "id": "booked-unrecorded",
      "reply": "Your meeting has been booked for 3pm.",
      "expectedPass": false,
      "expectedRules": [
        "action:unrecorded"
      ]
    },
    {
      "id": "uploaded-unrecorded",
      "reply": "The file was uploaded to your Drive.",
      "expectedPass": false,
      "expectedRules": [
        "action:unrecorded"
      ]
    },
    {
      "id": "success-assurance",
      "reply": "The tool call succeeded.",
      "expectedPass": false,
      "expectedRules": [
        "forbid:tool-success-assurance"
      ]
    },
    {
      "id": "api-confirmed",
      "reply": "The API confirmed your booking.",
      "expectedPass": false,
      "expectedRules": [
        "forbid:tool-success-assurance"
      ]
    },
    {
      "id": "result-contradicts-record",
      "reply": "I called the billing tool: your balance is $45.",
      "expectedPass": false,
      "expectedRules": [
        "fact:contradicts-record"
      ],
      "record": {
        "effects": [
          {
            "operation": "tool.call",
            "status": "DONE"
          }
        ],
        "facts": [
          {
            "near": "balance",
            "kind": "money",
            "value": "$40"
          }
        ]
      }
    },
    {
      "id": "time-contradicts-record",
      "reply": "Your meeting is at 4pm.",
      "expectedPass": false,
      "expectedRules": [
        "fact:contradicts-record"
      ],
      "record": {
        "facts": [
          {
            "near": "meeting",
            "kind": "time",
            "value": "3pm"
          }
        ]
      }
    },
    {
      "id": "format-strict",
      "reply": "Your balance is $40.00.",
      "expectedPass": false,
      "expectedRules": [
        "fact:contradicts-record"
      ],
      "record": {
        "facts": [
          {
            "near": "balance",
            "kind": "money",
            "value": "$40"
          }
        ]
      }
    },
    {
      "id": "called-recorded",
      "reply": "I called the search_orders tool and found your order.",
      "expectedPass": true,
      "expectedRules": [],
      "record": {
        "effects": [
          {
            "operation": "tool.call",
            "status": "DONE"
          }
        ]
      }
    },
    {
      "id": "result-matches-record",
      "reply": "I called the billing tool: your balance is $40.",
      "expectedPass": true,
      "expectedRules": [],
      "record": {
        "effects": [
          {
            "operation": "tool.call",
            "status": "DONE"
          }
        ],
        "facts": [
          {
            "near": "balance",
            "kind": "money",
            "value": "$40"
          }
        ]
      }
    },
    {
      "id": "pending",
      "reply": "I'll call the search tool now.",
      "expectedPass": true,
      "expectedRules": []
    },
    {
      "id": "question",
      "reply": "Should I send the email?",
      "expectedPass": true,
      "expectedRules": []
    },
    {
      "id": "honest-failure",
      "reply": "I couldn't reach the calendar tool, so nothing was booked.",
      "expectedPass": true,
      "expectedRules": []
    },
    {
      "id": "gap-tool-result-unrecorded",
      "reply": "The search tool returned 3 results.",
      "expectedPass": true,
      "expectedRules": []
    },
    {
      "id": "gap-bare-done",
      "reply": "Done! Posted to #general.",
      "expectedPass": true,
      "expectedRules": []
    },
    {
      "id": "gap-wrong-tool",
      "reply": "I called the refund tool.",
      "expectedPass": true,
      "expectedRules": [],
      "record": {
        "effects": [
          {
            "operation": "tool.call",
            "status": "DONE"
          }
        ]
      }
    }
  ]
}
