Receipts and verification
What a Felspar receipt records, how verification replays a decision, and what a receipt does and doesn't prove.
Every decision Felspar makes comes with a receipt. The receipt ties the decision to the exact release, the evidence the agent sent, the time of the decision and the result. Anyone allowed to can later ask Felspar to replay that decision and confirm the receipt matches.
Why receipts exist
An agent’s own account of what Felspar said can’t be trusted on its own: a model can misremember, paraphrase, or be manipulated by text it read. The receipt is Felspar’s record, not the agent’s. The code that acts on a decision checks the receipt with Felspar directly, so an action happens only when Felspar confirms the decision really was made, for that case, with that outcome.
The principle: whatever acts, verifies.
What a decision returns
| Field | Meaning |
|---|---|
result.executionObjectId |
The ID to verify this decision with |
result.releaseId, result.releaseDigest |
The exact release that decided |
result.evaluationTime |
When Felspar decided, by its own clock |
result.outcome |
The outcome, or null when undecided |
result.receipt |
The receipt, including receiptDigest |
result.context |
Context the release allows the agent to use for this outcome, if any |
result.explanation |
Why: the deciding rule quoted from the policy, open questions, when evidence stops being fresh |
Verifying a receipt
Send the receipt back to POST /v0/executions/{executionObjectId}/verify with its digest (and, optionally, the context you were given):
{
"receipt": { "...": "the receipt exactly as returned" },
"expectedReceiptDigest": "sha256:...",
"deliveredCapsule": { "...": "result.context, if you used it" }
}
Felspar loads the release, rebuilds the decision from what it recorded (the evidence, every classification, the original time) and compares it with your receipt, field by field. It calls no model. The answer:
{
"authority": "unapproved",
"status": "reproduced",
"mismatches": [],
"decided": {
"jobId": "classify-prospect",
"entityId": "tidewell.example",
"releaseId": "release-...",
"outcome": "platform_builder"
}
}
reproduced: the receipt matches a decision Felspar made. Usedecided(Felspar’s replay, not the agent’s claim) to check the job, the entity and the outcome before you act.mismatch: something differs.mismatchesnames what. Don’t act.authorityis always"unapproved". It is a fixed label saying the receipt itself certifies nothing beyond the replay: your team’s approval of the release is recorded on the release, not asserted by the receipt.
Who can verify
- A registered agent can verify receipts of decisions it made itself, with its own key, and no others.
- A person with inspection access in the workspace (any member, approver or owner) can verify any of the workspace’s decisions.
Verification is a REST call, not an MCP tool, on purpose: the code that performs an action should verify, not the model deciding what to do.
How long receipts can be verified
Decisions, their evidence and receipts are kept for 30 days from the first decision on a case. After that, verification is no longer possible. See Security, privacy and data.
What a receipt proves, and what it doesn’t
A reproduced receipt shows that:
- Felspar made this decision, under this exact release, from this exact evidence, at this time;
- replaying it today gives the same result.
It does not show that:
- the evidence was true. Felspar records what the agent said a source said; it doesn’t independently fetch or check the source;
- the policy is correct, lawful or compliant. A release records your team’s approval; it is not legal approval or certification;
- the agent then did what the outcome said. Felspar can only check actions that pass through a gate that asks it;
- an agent that never calls Felspar is governed by it.
Related
- The pre-action gate: verify in code before a tool acts.
- Verify receipts: a step-by-step guide.