Agent Output Verifier
Verifique independentemente a saída de um agente antes de pagar: estrutura, formatos, intervalos e regras entre campos, com atestado assinado e recibo. 3 chamadas gratuitas por dia, depois x402 v2.
Servidor MCP hospedado
npx add-mcp 'https://fastapi-service-5ag4.onrender.com/mcp'Instala no Claude Code, Codex, Cursor e outros
Documentação
Agent Output Verifier
Verifique de forma independente a saída de um agente antes de pagar.
Verificações independentes e determinísticas para faturas, entregas e qualquer saída estruturada: estrutura, formatos, intervalos e regras entre campos, como "os totais das linhas devem ser iguais ao total", de acordo com seus próprios requisitos, escritos em JSON Schema padrão, além de regras opcionais. Retorna aprovação/reprovação, a porcentagem de verificações aprovadas, dicas de correção e uma atestação e recibo assinados com Ed25519 que qualquer pessoa pode verificar com nossa chave pública. Vendedores: verifiquem sua própria saída antes de enviá-la e entreguem-na com uma atestação e recibo assinados. Sem cadastro: pague por chamada com x402 v2, em USDC na Base ou Solana. 3 chamadas gratuitas por dia via MCP.
Este repositório contém documentação e metadados públicos para o serviço hospedado — não há código-fonte
para instalar ou executar aqui. O serviço em si é uma API ao vivo em
https://fastapi-service-5ag4.onrender.com.
Endpoints
| Finalidade | Endpoint |
|---|---|
| MCP (HTTP Streamable) | https://fastapi-service-5ag4.onrender.com/mcp |
| Verificar uma saída (REST) | POST https://fastapi-service-5ag4.onrender.com/verify/schema |
| Consultar a pontuação de confiança de um agente (REST) | GET https://fastapi-service-5ag4.onrender.com/score/{agent_id} |
| Cartão do agente (descoberta) | GET https://fastapi-service-5ag4.onrender.com/.well-known/agent-card.json |
| Manifesto de descoberta x402 | GET https://fastapi-service-5ag4.onrender.com/.well-known/x402 |
| llms.txt | GET https://fastapi-service-5ag4.onrender.com/llms.txt |
| Documentação interativa da API | GET https://fastapi-service-5ag4.onrender.com/docs |
Duas ferramentas MCP são expostas no mesmo endpoint: verify_schema (POST /verify/schema) e
get_verification_record (GET /score/{agent_id}).
Preços e redes
Pago por chamada com x402 v2, em USDC, em qualquer uma das redes abaixo — sem conta ou cadastro:
| Rota | Preço | Redes |
|---|---|---|
POST /verify/schema | $0,02 USDC | Base (eip155:8453), Solana (solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp) |
GET /score/{agent_id} | $0,01 USDC | Base (eip155:8453), Solana (solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp) |
/.well-known/x402 e o cabeçalho Payment-Required de uma resposta 402 ao vivo sempre carregam os
preços exatos ao vivo, endereços de pagamento e endereços de ativos — trate-os como a fonte da verdade, e
esta tabela como uma referência rápida.
Três cabeçalhos carregam o pagamento em si, por nome: uma solicitação não paga recebe HTTP 402 com o preço e os
requisitos de pagamento no cabeçalho de resposta Payment-Required; uma solicitação paga carrega seu pagamento assinado
no cabeçalho de solicitação Payment-Signature; uma resposta liquidada carrega o recibo de liquidação
no cabeçalho de resposta Payment-Response. Um resultado fail é uma resposta completa e válida para a
pergunta feita e é cobrado da mesma forma que um pass — o trabalho (executar todas as verificações) é idêntico
em ambos os casos.
Teste gratuito
Cada ferramenta MCP tem sua própria cota de teste gratuito: 3 chamadas gratuitas por dia por cliente, identificadas pelo endereço IP da solicitação — sem cadastro ou conta — disponível via MCP. Chamadas REST e MCP do mesmo endereço compartilham uma cota por ferramenta.
O corpo 402 de uma chamada REST não paga relata o estado real deste chamador, ao vivo: available,
remaining_calls_today e resets_at (a próxima meia-noite UTC). Quando as chamadas do dia de um cliente
são usadas, available muda para false e o corpo carrega "code": "free_trial_exhausted" —
distinto de uma resposta comum de pagamento exigido que nunca teve teste gratuito para começar:
{
"free_trial": {
"available": false,
"via": "mcp",
"transport": "streamable-http",
"url": "https://fastapi-service-5ag4.onrender.com/mcp",
"tool": "verify_schema",
"calls_per_client_per_day": 3,
"remaining_calls_today": 0,
"resets_at": "2026-10-02T00:00:00+00:00",
"client": "identified by request IP address",
"message": "This client's 3 free calls/day for the MCP tool 'verify_schema' are used up for today; they reset at 2026-10-02T00:00:00+00:00. This REST endpoint has no free tier of its own.",
"code": "free_trial_exhausted"
}
}
O mesmo código free_trial_exhausted acompanha o resultado de pagamento exigido da própria ferramenta MCP
(em _meta) quando uma chamada de ferramenta é feita após as chamadas gratuitas do cliente para o dia acabarem. Após
o teste gratuito (ou quando ele se esgota no dia), uma chamada exige um pagamento x402 carregado na
solicitação MCP em _meta sob x402/payment, ou um cabeçalho de pagamento x402 padrão no REST.
Verificando um recibo, passo a passo
Toda resposta de /verify/schema e /score/{agent_id} carrega uma seção verify assinada e
um bloco attestation, por exemplo:
"verify": {
"public_key_url": "https://fastapi-service-5ag4.onrender.com/.well-known/agent-card.json",
"key_version": "v1-2026-09c",
"canonicalization": "RFC 8785 (JCS)",
"hash_algorithm": "SHA-256",
"service": "Agent Output Verifier",
"mcp": "https://fastapi-service-5ag4.onrender.com/mcp"
},
"attestation": {
"algorithm": "Ed25519",
"key_version": "v1-2026-09c",
"timestamp": "2026-10-01T01:01:09.606993+00:00",
"signature": "8UexIObSAwQxjj8/rbEpLRgbYY6XO+wg5+b0D8I3BRfbOxl+ouwcKNPE/hp+9p37Tm2wwdmCqPjBgOMLGQtGAQ=="
}
Nada além da própria resposta e verify.public_key_url é necessário:
-
Busque a chave pública.
GETo cartão do agente emverify.public_key_url. Sua matrizcapabilities.extensionstem uma entrada cujouricomeça comurn:json-schema-verifier:extension:attestation:; seuparams.publicKeyslista todas as chaves que o serviço já usou para assinar, cada uma{keyVersion, algorithm, publicKey}(a chave pública Ed25519 bruta de 32 bytes, codificada em base64). Escolha a entrada cujokeyVersionseja igual aresponse.attestation.key_version. O cartão do agente ao vivo é sempre a fonte da verdade; esta é uma cópia conveniente da chave atual, que vale a pena reconfirmar contra o cartão do agente ao vivo primeiro:{ "keyVersion": "v1-2026-09c", "algorithm": "Ed25519", "publicKey": "d2IHH0/Xduci/5J8IewYmauUvgqf+gFIeCEXDwjHUhw=", "publicKeyEncoding": "base64 of the raw 32-byte Ed25519 public key" } -
Reconstrua o documento assinado. É um objeto JSON com exatamente estas cinco chaves:
{ "context": "json-schema-verifier/verify-schema-attestation/v1", "algorithm": "Ed25519", "key_version": "<attestation.key_version>", "attested_at": "<attestation.timestamp>", "response": { "...": "the full response, with the attestation field removed" } }contextéjson-schema-verifier/verify-schema-attestation/v1para respostas/verify/schema, oujson-schema-verifier/trust-score-attestation/v1para respostas/score/{agent_id}. -
Canonicalize-o com RFC 8785 (JCS): bytes UTF-8 do documento JSON acima, chaves de objeto classificadas recursivamente, sem espaços em branco insignificantes, números impressos da maneira que o ECMAScript os imprime (
1.0torna-se1). -
Verifique a assinatura Ed25519 (
response.attestation.signature, decodificada em base64) sobre esses bytes canônicos, usando a chave pública do passo 1. -
Verifique os quatro hashes do recibo, cada SHA-256 sobre o JSON canônico RFC 8785 (JCS) do valor nomeado:
output_hash(desubmitted_output),schema_hash(deexpected_schema),rules_hash(de{"bounds": ..., "rules": ...}) erequest_hash(de toda a solicitação como analisada, apenas detalhe completo). Recalcule-os você mesmo e compare — é isso que vincula o recibo aos dados exatos que foram verificados.request_hashpreenche cada campo por regra e por limite com seu próprio padrão antes de aplicar hash — umtoleranceomitido tem hash como1e-9, umif_presentomitido comofalse, umequals_field/equals/other_field/value/in_field/valuesomitido comonull— então duas solicitações cujas regras diferem apenas em quais campos opcionais foram digitados ainda têm hash idêntico aqui.rules_hashé o oposto: ele aplica hash exatamente e apenas aos campos que você forneceu, nada preenchido por padrão.
Um verificador Python mínimo, usando apenas a biblioteca padrão mais cryptography:
import base64, json
from decimal import Decimal
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
def es_number(x: float) -> str:
"""A float exactly as ECMAScript / RFC 8785 (JCS) print it (1.0 -> "1", 1e-7 -> "1e-7")."""
if x == 0:
return "0"
sign = "-" if x < 0 else ""
digits_tuple = Decimal(repr(abs(x))).as_tuple()
digits = "".join(map(str, digits_tuple.digits)).rstrip("0") or "0"
n = len(digits_tuple.digits) + digits_tuple.exponent # position of the decimal point
k = len(digits)
if k <= n <= 21:
body = digits + "0" * (n - k)
elif 0 < n <= 21:
body = digits[:n] + "." + digits[n:]
elif -6 < n <= 0:
body = "0." + "0" * (-n) + digits
else:
e = n - 1
body = digits[0] + ("." + digits[1:] if k > 1 else "") + f"e{'+' if e >= 0 else '-'}{abs(e)}"
return sign + body
def canonical(v) -> str:
if isinstance(v, bool):
return "true" if v else "false"
if isinstance(v, float):
return es_number(v)
if isinstance(v, dict):
return "{" + ",".join(f"{canonical(k)}:{canonical(v[k])}" for k in sorted(v)) + "}"
if isinstance(v, list):
return "[" + ",".join(canonical(x) for x in v) + "]"
return json.dumps(v, ensure_ascii=False) # covers None, int, str
def verify(response: dict, public_key_b64: str, context: str) -> bool:
att = response["attestation"]
body = {k: v for k, v in response.items() if k != "attestation"}
message = canonical({
"context": context,
"algorithm": att["algorithm"],
"key_version": att["key_version"],
"attested_at": att["timestamp"],
"response": body,
}).encode("utf-8")
key = Ed25519PublicKey.from_public_bytes(base64.b64decode(public_key_b64))
try:
key.verify(base64.b64decode(att["signature"]), message)
return True
except Exception:
return False
Testado contra ambos os recibos no exemplo prático abaixo — ambos verificam True.
Exemplo prático: verificação de fatura
Ambas as chamadas abaixo são genuínas, ao vivo e pagas contra o serviço de produção — pagamentos x402
reais na Base, liquidados on-chain, com os recibos assinados resultantes mostrados exatamente como recebidos.
Ambos são verificáveis de forma independente: busque o cartão do agente acima, confirme que key_version: v1-2026-09c
está listado e verifique cada attestation.signature com os passos acima.
1. Fatura de rascunho — falha em uma regra entre campos (detail: "full")
Solicitação:
{
"task_id": "invoice-7731-draft",
"agent_id": "test-seller-invoice-agent",
"expected_schema": {
"type": "object",
"required": ["invoice_id", "currency", "line_items", "total"],
"properties": {
"invoice_id": { "type": "string", "pattern": "^INV-[0-9]{4}$" },
"currency": { "enum": ["USD", "EUR"] },
"line_items": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["sku", "qty", "line_total"],
"properties": {
"sku": { "type": "string" },
"qty": { "type": "integer", "minimum": 1 },
"line_total": { "type": "number", "minimum": 0 }
}
}
},
"total": { "type": "number" }
}
},
"submitted_output": {
"invoice_id": "INV-7731",
"currency": "USD",
"line_items": [
{ "sku": "CRWL-100", "qty": 3, "line_total": 87.0 },
{ "sku": "CRWL-200", "qty": 1, "line_total": 42.5 }
],
"total": 135.0
},
"rules": [
{ "type": "sum_equals", "field": "line_items[].line_total", "equals_field": "total" }
],
"enforce_rules": true,
"detail": "full"
}
Os itens de linha somam 129,5, mas total diz 135,0. Com enforce_rules: true, essa violação
de regra reprova o resultado e vem com uma dica de correção:
{
"summary": {
"result": "fail",
"blocking_checks": ["consistency:sum_equals"]
},
"next_actions": [
{ "action": "repair_and_reverify", "using": "hints" }
],
"result": "fail",
"verification_id": "28afb453-7c39-4993-a9c4-fcade1b7924f",
"task_id": "invoice-7731-draft",
"agent_id": "test-seller-invoice-agent",
"output_hash": "d4fb804e434eb3ee047068cbb3691ea1e07066928e7e3efc73b94317e53ee305",
"schema_hash": "23ea3213715cfaf2011dabe2a9a69d4ac25b6eceec7ce3d4bfef9a1298b69b2a",
"rules_hash": "2acb6de92b88cfbca279ea6d5bd74b7a1e7dec0839dd093dbe041e25df3364d2",
"request_hash": "e4bf9733726b24a19ec546ecc79015c9b1cb7a6829b409b41ef56b1c8f60b881",
"verified_at": "2026-10-01T01:01:09.606993+00:00",
"verifier_version": "0.4.1",
"enforce_rules": true,
"strict_content_check": false,
"errors": [
"enforce_rules: consistency:sum_equals at 'line_items[].line_total': values sum to 129.5, expected total (135.0)"
],
"errors_total": 1,
"errors_omitted": 0,
"errors_detail": [
{
"check": "consistency:sum_equals",
"path": "$.line_items[].line_total",
"expected": "a sum equal to total (135.0)",
"found": "sum 129.5",
"message": "enforce_rules: consistency:sum_equals at 'line_items[].line_total': values sum to 129.5, expected total (135.0)"
}
],
"errors_detail_total": 1,
"errors_detail_omitted": 0,
"flags": [
{
"check": "consistency:sum_equals",
"field": "line_items[].line_total",
"severity": "error",
"detail": "values sum to 129.5, expected total (135.0)"
}
],
"flags_total": 1,
"flags_omitted": 0,
"hints": [
{
"source": "integrity",
"check": "consistency:sum_equals",
"path": "$.line_items[].line_total",
"expected": "a sum equal to total (135.0)",
"found": "sum 129.5"
}
],
"hints_total": 1,
"hints_omitted": 0,
"schema_compliance": { "ratio": 1.0, "passed": 22, "total": 22 },
"integrity_checks": { "ratio": 0.875, "passed": 7, "total": 8 },
"overall": { "ratio": 0.966667, "passed": 29, "total": 30 },
"verify": {
"public_key_url": "https://fastapi-service-5ag4.onrender.com/.well-known/agent-card.json",
"key_version": "v1-2026-09c",
"canonicalization": "RFC 8785 (JCS)",
"hash_algorithm": "SHA-256",
"service": "Agent Output Verifier",
"mcp": "https://fastapi-service-5ag4.onrender.com/mcp"
},
"attestation": {
"algorithm": "Ed25519",
"key_version": "v1-2026-09c",
"timestamp": "2026-10-01T01:01:09.606993+00:00",
"signature": "8UexIObSAwQxjj8/rbEpLRgbYY6XO+wg5+b0D8I3BRfbOxl+ouwcKNPE/hp+9p37Tm2wwdmCqPjBgOMLGQtGAQ=="
}
}
Evidência de pagamento: $0,02 USDC na Base, liquidado on-chain —
0x4cb755c71413ed5419215d2d7445c34e19be79d9f15b4046802656165b774897.
2. Fatura corrigida — passa (detail: "compact")
Mesmo esquema e regra, total corrigido para corresponder aos itens de linha (129,5), solicitado com
"detail": "compact" para obter apenas o resumo, os campos do recibo e a assinatura:
{
"task_id": "invoice-7731-final",
"agent_id": "test-seller-invoice-agent",
"expected_schema": { "...": "same schema as above" },
"submitted_output": {
"invoice_id": "INV-7731",
"currency": "USD",
"line_items": [
{ "sku": "CRWL-100", "qty": 3, "line_total": 87.0 },
{ "sku": "CRWL-200", "qty": 1, "line_total": 42.5 }
],
"total": 129.5
},
"rules": [
{ "type": "sum_equals", "field": "line_items[].line_total", "equals_field": "total" }
],
"enforce_rules": true,
"detail": "compact"
}
{
"summary": {
"result": "pass",
"blocking_checks": []
},
"next_actions": [
{ "action": "attach_receipt", "for": "seller" },
{ "action": "proceed_to_payment", "for": "buyer" }
],
"result": "pass",
"verification_id": "96b4f722-04c3-47c7-8708-5bba97fd18b5",
"task_id": "invoice-7731-final",
"agent_id": "test-seller-invoice-agent",
"output_hash": "39e3d0a1431e3ce9cda89a1d2873e1ffb4e34f4eeded2ffa87946fbd941a34c3",
"schema_hash": "23ea3213715cfaf2011dabe2a9a69d4ac25b6eceec7ce3d4bfef9a1298b69b2a",
"rules_hash": "2acb6de92b88cfbca279ea6d5bd74b7a1e7dec0839dd093dbe041e25df3364d2",
"verified_at": "2026-10-01T01:01:15.158857+00:00",
"verifier_version": "0.4.1",
"enforce_rules": true,
"strict_content_check": false,
"verify": {
"public_key_url": "https://fastapi-service-5ag4.onrender.com/.well-known/agent-card.json",
"key_version": "v1-2026-09c",
"canonicalization": "RFC 8785 (JCS)",
"hash_algorithm": "SHA-256",
"service": "Agent Output Verifier",
"mcp": "https://fastapi-service-5ag4.onrender.com/mcp"
},
"attestation": {
"algorithm": "Ed25519",
"key_version": "v1-2026-09c",
"timestamp": "2026-10-01T01:01:15.158857+00:00",
"signature": "ri1AEl12DoZMTKBX8V5hfuD9jOWd+BLXIciqiX1JoSHJy8iDJKKSdsJmjpQUHTkbVMxDGpNwMNmc6X9zHaSVDw=="
}
}
A forma compacta mantém o resumo, os campos do recibo, verify e attestation; request_hash,
errors, errors_detail, flags, hints e as três pontuações permanecem na forma completa (veja
detail acima).
Evidência de pagamento: $0,02 USDC na Base, liquidado on-chain —
0xaa9161736ac410b6ac9ccc478780aa2feaa6d2cf02af4c51855e099c14499079.
Verificando esses dois recibos você mesmo
Ambas as respostas acima foram verificadas contra a chave pública do cartão do agente ao vivo para v1-2026-09c
antes de serem incluídas aqui, usando os passos em Verificando um recibo.
Confirme você mesmo da mesma forma: busque
https://fastapi-service-5ag4.onrender.com/.well-known/agent-card.json, confirme que v1-2026-09c está
listado e execute novamente os mesmos cinco passos contra os dois blocos JSON acima — as assinaturas foram
calculadas uma vez, exatamente sobre esses dados, e serão verificadas de forma idêntica para qualquer pessoa.
agent_id identifica o agente que produziu a saída que está sendo verificada — por exemplo, o vendedor;
é um rótulo não autenticado fornecido pelo chamador. agent_id: "test-seller-invoice-agent" usa o
prefixo test- que o serviço reserva para exemplos: a verificação foi executada de verdade, e seu recibo é
genuíno, permanecendo separado da pontuação de confiança desse agente.
Licença
Documentação e exemplos neste repositório são licenciados sob a Licença MIT. O serviço hospedado é proprietário; este repositório contém apenas documentação e metadados públicos.