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

FinalidadeEndpoint
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 x402GET https://fastapi-service-5ag4.onrender.com/.well-known/x402
llms.txtGET https://fastapi-service-5ag4.onrender.com/llms.txt
Documentação interativa da APIGET 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:

RotaPreçoRedes
POST /verify/schema$0,02 USDCBase (eip155:8453), Solana (solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp)
GET /score/{agent_id}$0,01 USDCBase (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:

  1. Busque a chave pública. GET o cartão do agente em verify.public_key_url. Sua matriz capabilities.extensions tem uma entrada cujo uri começa com urn:json-schema-verifier:extension:attestation:; seu params.publicKeys lista 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 cujo keyVersion seja igual a response.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"
    }
    
  2. 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/v1 para respostas /verify/schema, ou json-schema-verifier/trust-score-attestation/v1 para respostas /score/{agent_id}.

  3. 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.0 torna-se 1).

  4. Verifique a assinatura Ed25519 (response.attestation.signature, decodificada em base64) sobre esses bytes canônicos, usando a chave pública do passo 1.

  5. Verifique os quatro hashes do recibo, cada SHA-256 sobre o JSON canônico RFC 8785 (JCS) do valor nomeado: output_hash (de submitted_output), schema_hash (de expected_schema), rules_hash (de {"bounds": ..., "rules": ...}) e request_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_hash preenche cada campo por regra e por limite com seu próprio padrão antes de aplicar hash — um tolerance omitido tem hash como 1e-9, um if_present omitido como false, um equals_field/equals/other_field/value/in_field/ values omitido como null — 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.