Assert an agent’s output
Assert the answer before it goes anywhere. An agent was told: “Summarise this source in JSON with a summary, one
quotation from it, and the source_url.” A second call checks it: the JSON validates against the schema the caller wrote,
the quotation appears verbatim in the source as the caller supplied it, a URL is present and under the allowed domain,
and none of the usual hedges appear. Every check is a deterministic function of the inputs, so the same output gets the
same verdict every time, and the answer is a signed Assay record that names which check failed and where. The second answer
below fabricates its quotation; the record says so.
Run 2026-10-11 05:26 UTC against api.s2ar.dev 0.1.1 · 3 calls · 338 ms · list price $0.01 for a stranger (these ran on the operator's key and cost nothing) · every number on this page re-derived by tools/walkthrough.py before it was written
1. The quote: HTTP 402
The price, the rails, the determinism and the witnesses of this route, and where the worked example lives. The quote costs nothing.
curl -s -X POST 'https://api.s2ar.dev/v1/assert' \
-H 'X-Assay-Quote: 1' \
-H 'content-type: application/json' \
-d '{"text": "{\"summary\": \"ripgrep parses the --glob flag in defs.rs; later globs override earlier ones.\", \"quote\": \"Overrides are applied in order of appearance on the command line\", \"source_url\": \"https://github.com/BurntSushi/ripgrep\"}", "checks": [{"check": "json_valid"}]}'
| price_usd | 0.005 |
|---|---|
| rails | ["x402", "credits"] |
| determinism | replayable |
| witnesses | ["checks"] |
| expected_latency_ms | 300 |
| free.per_day_keyless | 10 |
| how_to_pay | Pay per call with USDC on Base over x402 (no key: sign the 402's accepts[0], resend with PAYMENT-SIGNATURE); or buy a $5 pack by card and send Authorization:… |
| docs | https://s2ar.dev/examples/assert-an-agents-output.html |
the answer, as JSON
{
"price_usd": 0.005,
"rails": [
"x402",
"credits"
],
"determinism": "replayable",
"witnesses": [
"checks"
],
"expected_latency_ms": 300,
"free.per_day_keyless": 10,
"how_to_pay": "Pay per call with USDC on Base over x402 (no key: sign the 402's accepts[0], resend with PAYMENT-SIGNATURE); or buy a $5 pack by card and send Authorization:…",
"docs": "https://s2ar.dev/examples/assert-an-agents-output.html"
}
2. An answer that holds
Four checks, four passes: the JSON validates, the quotation is in the source word for word, the URL is under github.com, no hedge.
curl -s -X POST 'https://api.s2ar.dev/v1/assert' \
-H "Authorization: Bearer $S2AR_KEY" \
-H 'content-type: application/json' \
-d '{"text": "{\"summary\": \"ripgrep parses the --glob flag in defs.rs; later globs override earlier ones.\", \"quote\": \"Overrides are applied in order of appearance on the command line\", \"source_url\": \"https://github.com/BurntSushi/ripgrep\"}", "source": "The glob flag is parsed in crates/core/flags/defs.rs. Each flag is a type implementing the Flag trait, with a short name, a long name and a documentation string. Overrides are applied in order of appearance on the command line, so a later --glob can undo an earlier one.", "checks": [{"check": "json_schema", "schema": {"type": "object", "required": ["summary", "quote", "source_url"], "properties": {"summary": {"type": "string", "maxLength": 200}, "quote": {"type": "string"}, "source_url": {"type": "string"}}}}, {"check": "quotes_in_source"}, {"check": "urls_allowed", "domains": ["github.com"]}, {"check": "banned_terms", "terms": ["I cannot", "as an AI", "I'm not sure"]}]}'
PARTIAL
| verdict | partial |
|---|---|
| passed | 3 |
| checks | 4 |
| score | 0.75 |
| results.0.check | json_schema |
| results.0.ok | true |
| results.1.check | quotes_in_source |
| results.1.ok | false |
| results.1.evidence | {"quotes": 2, "missing": ["ripgrep parses the --glob flag in defs.rs; later globs override earlier ones."]} |
| record.kind | assertion |
| record.issuer | assay |
| record.replayable | true |
| record_sha256 | 11dcc16c0d1402c0… |
| x-assay-record | 11dcc16c0d1402c0… |
the answer, as JSON
{
"verdict": "partial",
"passed": 3,
"checks": 4,
"score": 0.75,
"results.0.check": "json_schema",
"results.0.ok": true,
"results.1.check": "quotes_in_source",
"results.1.ok": false,
"results.1.evidence": {
"quotes": 2,
"missing": [
"ripgrep parses the --glob flag in defs.rs; later globs override earlier ones."
]
},
"record.kind": "assertion",
"record.issuer": "assay",
"record.replayable": true,
"record_sha256": "11dcc16c0d1402c086d05906d73d637092e42d8d0e837589685b72530b8c10ba",
"x-assay-record": "11dcc16c0d1402c086d05906d73d637092e42d8d0e837589685b72530b8c10ba"
}
| re-derived by the generator | |
|---|---|
| ✓ | receipt sha256:709c64a987b51f19… re-derived: sha256 over the canonical answer, header and body agree |
| ✓ | record 11dcc16c0d1402c0… fetched back from /v1/verify: sealed, signed, and signed by assay-1 (the key at /.well-known/assay.json) |
3. An answer that fabricates its quotation
The schema still validates; the quotation is not in the source and a hedge slipped in: two of four checks fail, and the evidence names the missing quote and the hedge’s offset. The call is delivered, charged and recorded: the evidence is the answer.
curl -s -X POST 'https://api.s2ar.dev/v1/assert' \
-H "Authorization: Bearer $S2AR_KEY" \
-H 'content-type: application/json' \
-d '{"text": "{\"summary\": \"ripgrep parses globs in defs.rs; I cannot be sure which wins.\", \"quote\": \"the last glob always wins and earlier ones are discarded\", \"source_url\": \"https://github.com/BurntSushi/ripgrep\"}", "source": "The glob flag is parsed in crates/core/flags/defs.rs. Each flag is a type implementing the Flag trait, with a short name, a long name and a documentation string. Overrides are applied in order of appearance on the command line, so a later --glob can undo an earlier one.", "checks": [{"check": "json_schema", "schema": {"type": "object", "required": ["summary", "quote", "source_url"]}}, {"check": "quotes_in_source"}, {"check": "urls_allowed", "domains": ["github.com"]}, {"check": "banned_terms", "terms": ["I cannot", "as an AI", "I'm not sure"]}]}'
PARTIAL
| verdict | partial |
|---|---|
| passed | 2 |
| checks | 4 |
| results.1.check | quotes_in_source |
| results.1.ok | false |
| results.1.evidence.missing | ["ripgrep parses globs in defs.rs; I cannot be sure which wins.", "the last glob always wins and earlier ones are discarded"] |
| results.3.check | banned_terms |
| results.3.ok | false |
| results.3.evidence.found | [{"term": "I cannot", "offset": 46}] |
| record.outcome | partial |
| record_sha256 | 2178d867d06fe537… |
the answer, as JSON
{
"verdict": "partial",
"passed": 2,
"checks": 4,
"results.1.check": "quotes_in_source",
"results.1.ok": false,
"results.1.evidence.missing": [
"ripgrep parses globs in defs.rs; I cannot be sure which wins.",
"the last glob always wins and earlier ones are discarded"
],
"results.3.check": "banned_terms",
"results.3.ok": false,
"results.3.evidence.found": [
{
"term": "I cannot",
"offset": 46
}
],
"record.outcome": "partial",
"record_sha256": "2178d867d06fe537131608c173220ef92bb7c6e7831d293cb1960fab2b10dc45"
}
| re-derived by the generator | |
|---|---|
| ✓ | receipt sha256:8c0538ce649f06f2… re-derived: sha256 over the canonical answer, header and body agree |
| ✓ | record 2178d867d06fe537… fetched back from /v1/verify: sealed, signed, and signed by assay-1 (the key at /.well-known/assay.json) |
The record carries the checks, each result and the sha256 of the text and the source, never the text: anyone
holding the output can re-run the checks, and anyone at all can check the seal and the signature, free, at
/v1/verify/<record_sha256>. Read the verdict for what it is: quotes_in_source proves the output is consistent
with the source as given (its hash is in the record), not that the source is true or complete; a reader who
cares compares source_sha256 with the document they trust. An agent calls the same route as GET /v1/assert?text=&checks=, or the
assert_output tool over MCP; GET /v1/assert/checks lists the check kinds and the named rubrics.
What this cannot buy
From the signed proceedings (/.well-known/proceedings.json), verbatim:
- placement or routing position
- a different verdict or grade
- buyer data
- amendment access
- a revocation
Failed calls are never charged. Nothing about a caller is kept. The rules: the charter.