INAM Protocol (inam-mcp)

Verifique o histórico de trabalho assinado de um agente de IA antes de pagar ou contratá-lo. x402 verificação antes do pagamento, recibos de trabalho entre duas partes, reputação baseada em evidências.

Documentação

INAM Protocol logo

Registro do Protocolo Inam

npm PyPI npm CI License

Seu agente verifica para quem está pagando antes de pagar. Um pagamento x402 só é liberado se o ID INAM do beneficiário comprovar o controle da carteira payTo e tiver trabalho que uma contraparte real tenha assinado. Um servidor que empresta o ID de um agente respeitável para receber o dinheiro não recebe nada.

npm run demo:x402: the honest seller is paid; an endpoint borrowing the seller's INAM ID with someone else's wallet is blocked; a newcomer with no work history is blocked

Experimente (um comando, local, sem dinheiro real, sem cadastro):

git clone https://github.com/inamprotocol/inam-protocol && cd inam-protocol
npm install && npm --prefix sdk-js install
npm run demo:x402

Dê ao seu próprio agente uma identidade e seu primeiro recibo com assinatura dupla, em cerca de um minuto, contra o registro ao vivo. O agente de demonstração do registro é a outra parte (SPEC §14; recibos de demonstração nunca contam para a reputação):

npm i inamprotocol
curl -sO https://raw.githubusercontent.com/inamprotocol/inam-protocol/main/examples/quickstart.mjs && node quickstart.mjs

No seu próprio agente, é um único wrapper em torno de fetch: withInamX402Gate(fetch, client, { minEvidence: "countersigned" }) (SDK TypeScript, examples/x402-verify-before-pay.ts, SPEC §11.2). Os limites são seus; checkTrust() fornece a mesma decisão de permitir / reter / negar fora do x402.

Por baixo, o INAM é um registro aberto do trabalho dos agentes: ambos os lados assinam um recibo para cada tarefa concluída, e a reputação é calculada apenas a partir desses recibos. O INAM não é um protocolo de comunicação entre agentes (isso é MCP/A2A), não é um substituto de identidade ou autorização (isso é AgentPass/AITP/Passport Alliance/DID) e não é um runtime de agentes — é o registro neutro de "este trabalho realmente aconteceu entre estes dois agentes, e aqui está seu histórico baseado em evidências." Especificação completa: SPEC.md, também legível em docs.inamprotocol.org junto com uma referência interativa da API gerada a partir de openapi.yaml (fonte em docs-site/).

Por que isso existe

Um estudo empírico de 2026 sobre o ERC-8004, o padrão de reputação de agentes da Ethereum (arXiv 2606.26028), descobriu que 95–100% do seu feedback não estava vinculado a nenhuma tarefa ou pagamento, e que 59–91% dos revisores mostravam comportamento Sybil coordenado. A conclusão foi que o registro "não pode funcionar como um sinal confiável de confiança." Qualquer pessoa pode publicar uma pontuação, então as pontuações significam pouco.

O INAM não tem pontuação independente para publicar. Cada sinal de confiança é construído a partir de evidências:

  1. Recibos assinados por duas partes. A reputação de um agente vem apenas de Recibos de Execução que ambas as partes assinaram, cada um nomeando uma tarefa, um hash de especificação e um hash de saída. O ID do recibo é o hash do seu conteúdo, então não pode ser editado depois.
  2. Pontuação com desconto Sybil. As contrapartes são ponderadas pela sua própria confiança, pares repetidos contam de forma sublinear e o histórico antigo decai. Identidades descartáveis que se avaliam mutuamente não movem a pontuação.
  3. Verificadores autorizados pelo operador. Atestações independentes contam apenas de verificadores explicitamente concedidos pelo operador do registro (sem autoatendimento). Um veredito rejected conta como falha. Cada relatório de reputação informa seu evidenceLevel: none, countersigned ou independently_verified. Os mantenedores executam um verificador de integridade ao vivo contra o registro público a cada hora.
  4. Histórico à prova de adulteração. Cada recibo finalizado é anexado a um log de transparência Merkle estilo RFC 6962. Um monitor externo verifica cada nova raiz da árvore quanto à consistência a cada hora, e seu histórico é público no branch monitor-state.

O INAM compõe com o ERC-8004 em vez de competir com ele na camada de identidade: uma identidade ERC-8004 pode ser vinculada a um ID INAM com uma assinatura de carteira padrão (SPEC §11.1).

O que essas defesas não cobrem está listado em THREAT-MODEL.md. Quem decide o quê, e o que o operador do registro público se compromete, está em GOVERNANCE.md.

Este repositório

Este diretório é a implementação de referência em Node/TypeScript: servidor de registro Express, identidade did:key, mecanismo de reputação resistente a Sybil e o SDK InamClient. O SDK em si é publicado de forma independente como inamprotocol (fonte em sdk-js/ — o código exato que este servidor e a implantação Worker importam, não uma compilação separada). Um SDK Python de paridade é publicado como inamprotocol no PyPI (fonte em sdk-python/). Node 22 — zero dependências nativas (criptografia JS pura e o armazenamento node:sqlite embutido), então npm install nunca precisa de um toolchain C++.

Execute

Novo aqui? Comece com QUICKSTART.md — do zero a uma pontuação de reputação real e alterada em cerca de dois minutos, contra o registro ao vivo.

Autohospedagem com Docker

git clone https://github.com/inamprotocol/inam-protocol && cd inam-protocol
docker compose up -d     # registry on http://localhost:4021, data in the inam-data volume

Aponte qualquer SDK para http://localhost:4021 em vez da API ao vivo. Defina INAM_OPERATOR_DID (um did:key) no ambiente antes de up se quiser conceder status de verificador (SPEC §12.3); se não for definido, ninguém pode. docker compose down -v apaga os dados.

Executando um registro privado para os agentes da sua própria equipe (imagem pré-construída, backups, explorador, recibos privados): SELF-HOSTING.md.

A partir do código-fonte

sdk-js é um pacote aninhado separado que este servidor importa diretamente por caminho relativo (veja "O que há aqui" abaixo), então ele também precisa do seu próprio npm install — veja CONTRIBUTING.md se npm run dev falhar com um erro de módulo ausente.

npm install
cd sdk-js && npm install && cd ..
npm run dev      # starts the API on http://localhost:4021
npm run demo     # in another terminal: registers two agents, links an external
                  # identity, runs two jobs end to end, prints the resulting
                  # reputation
npm test         # canonical-JSON, did:key/signing, and receipt-lifecycle tests

Os dados são persistidos em data/registry.db (SQLite, ignorado pelo git). Exclua essa pasta para redefinir o registro para vazio. Os testes nunca a tocam — eles são executados contra um diretório temporário novo (veja tests/setupEnv.ts).

Demonstração de interoperabilidade entre linguagens

bash scripts/run-interop-demo.sh

Registra um "solicitante" no lado TypeScript e um "trabalhador" no lado Python (veja sdk-python/) contra o mesmo servidor ao vivo, faz o trabalhador Python enviar dois rascunhos de Recibo de Execução assinados, faz o solicitante TypeScript assiná-los e imprime a reputação resultante do trabalhador. Esta é a prova ponta a ponta real de que o protocolo — não apenas um SDK — funciona: o servidor verifica assinaturas Ed25519 produzidas em Python, e ambos os SDKs concordam byte por byte no JSON canônico. Veja sdk-python/tests/test_interop.py para a mesma garantia como um teste de unidade rápido, sem necessidade de servidor.

Implantação ao vivo

worker/ é uma segunda implementação independente da mesma superfície de API — Hono + Cloudflare D1 (SQL) + KV (cache de idempotência), implantada em Cloudflare Workers — mantida comportamentalmente idêntica ao servidor de referência Node (mesmas rotas, mesmo esquema de assinatura, mesma matemática de reputação; verificado executando os scripts de demonstração e smoke-test contra ambos e comparando a saída). Ele reutiliza sdk-js/src/crypto/ e sdk-js/src/core/receiptContent.ts inalterados em vez de reimplementá-los, então o núcleo criptográfico tem exatamente uma fonte de verdade em todos os três runtimes (Node, Workers, Python).

Atualmente ao vivo em https://api.inamprotocol.org (domínio personalizado, vinculado via worker/wrangler.jsonc; a URL *.workers.dev também funciona como fallback).

cd worker
npm install
npm run dev              # local dev server (D1 + KV emulated locally)
npm run deploy            # deploy to Cloudflare
npm run db:init:local     # apply schema.sql to the local D1 emulation
npm run db:init:remote    # apply schema.sql to the real remote D1 database

scripts/worker-smoke-test.ts (executado com INAM_URL apontado para uma instância wrangler dev local ou a implantação ao vivo) exercita especificamente as partes que são novas nesta implantação, em vez das compartilhadas com o servidor Node: roteamento, consultas D1 e idempotência baseada em KV — registro duplicado, autonegociação, recibos duplicados, rejeição de assinante errado, replay idempotente e o fluxo de disputa.

SDKs

npm install inamprotocol
pip install inamprotocol
import { InamClient, generateKeypair } from "inamprotocol";

const client = new InamClient("https://api.inamprotocol.org", generateKeypair());
const profile = await client.registerAgent(["document-extraction"]);

Veja sdk-js/README.md e sdk-python/README.md para a superfície completa do cliente (tarefas, recibos, reputação).

De um agente de IA (MCP / Claude Code)

Qualquer cliente MCP pode usar o registro através de inam-mcp (fonte em mcp/):

claude mcp add inam npx -y inam-mcp

Ou, somente leitura, sem nada para instalar, aponte qualquer cliente MCP Streamable HTTP para o endpoint hospedado https://api.inamprotocol.org/mcp (claude mcp add --transport http inam https://api.inamprotocol.org/mcp).

No Claude Code, o plugin INAM inclui uma skill que orienta você na exploração do registro, execução de um ciclo de demonstração de tarefa/recibo e registro de uma identidade de agente (detalhes em inam-protocol-plugin/):

/plugin marketplace add inamprotocol/inam-protocol
/plugin install inam-protocol@inam-protocol-plugins

O que há aqui

  • sdk-js/ — o pacote npm publicado inamprotocol: codificação/decodificação did:key (Ed25519), assinatura/verificação, o serializador JSON canônico de subconjunto JCS, IDs de recibo com endereçamento por conteúdo e InamClient. Este servidor (src/services/receiptService.ts, src/middleware/signedRequest.ts) e o Cloudflare Worker (worker/src/receiptService.ts, worker/src/signedRequest.ts) importam esses arquivos diretamente por caminho relativo em vez de depender do pacote compilado — há exatamente uma implementação da lógica de criptografia/canonicalização/conteúdo de recibo em todos os runtimes TypeScript neste repositório.
  • src/middleware/signedRequest.ts — autenticação de solicitação: toda chamada mutável é assinada pela própria chave do chamador, não por uma chave de API. Esquema simplificado inspirado no RFC 9421 (veja o comentário de documentação do arquivo para o contrato exato de cabeçalho e por que não é conformidade total com o RFC 9421).
  • src/services/receiptService.ts — o ciclo de vida do Recibo de Execução: IDs com endereçamento por conteúdo, rascunho → assinatura dupla → finalizado, janela de disputa.
  • src/services/jobService.ts / worker/src/jobService.ts — o recurso opcional de Tarefa (SPEC.md §3): aberta → aceita → concluída/cancelada, ofertas e a verificação de consistência que vincula um recibo finalizado de volta à tarefa que ele conclui. Implementado em ambos os runtimes e ambos os SDKs.
  • src/services/verificationService.ts / worker/src/verificationService.ts — o recurso de Verificação (SPEC.md §12): a atestação assinada de um único verificador independente de que a saída de um recibo finalizado satisfaz os requisitos de sua tarefa, alimentando um aumento de peso na reputação. Implementado em ambos os runtimes e ambos os SDKs.
  • src/services/reputationService.ts — o mecanismo de pontuação resistente a Sybil: ponderação de confiança da contraparte, ponderação sublinear de pares (resistência a wash-trading), decaimento temporal, componente de participação, sinalizador de contraparte concentrada, aumento de verificação independente.
  • src/services/badgeService.ts / worker/src/badgeService.ts — o selo de reputação incorporável (GET /agents/:id/badge.svg / .json): uma camada de renderização sobre a saída de computeReputation(), não um segundo mecanismo de pontuação. Nunca interpola texto fornecido pelo agente (por exemplo, metadata.name) no SVG — apenas o rótulo fixo "inam" e uma pontuação/status calculados pelo servidor.
  • sdk-js/src/core/receiptContent.ts — a única peça de lógica que todo SDK, em qualquer linguagem, deve concordar byte por byte: forma do conteúdo do recibo e cálculo do ID com endereçamento por conteúdo. O SDK Python tem seu próprio port linha por linha (sdk-python/inamprotocol/receipt.py), verificado contra vetores de teste fixos entre linguagens.
  • sdk-js/src/client.ts — InamClient. A camada de chamada de ferramentas de um framework de agentes envolveria essas mesmas chamadas como ferramentas search_jobs / verify_agent / submit_work.
  • sdk-python/ — SDK Python de paridade (InamClient), com sua própria suíte de testes incluindo a verificação de interoperabilidade entre linguagens descrita acima.
  • scripts/demo.ts — um cenário executável de dois agentes usando o cliente SDK contra um servidor ao vivo.
  • scripts/interop-phase-*.ts + sdk-python/examples/interop_worker.py — as três fases da demonstração entre linguagens (veja scripts/run-interop-demo.sh para executar todas juntas).

Superfície da API (/v1)

Especificação legível por máquina: openapi.yaml (valida limpo com npx @redocly/cli lint openapi.yaml).

POST /agents                     register (signed)
GET  /agents/:id
GET  /agents/:id/protocols
GET  /agents/:id/reputation
GET  /agents/:id/badge.svg        embeddable shields.io-style trust-score badge (unsigned, public)
GET  /agents/:id/badge.json       same badge data as JSON, for a custom renderer
GET  /agents/:id/receipts
GET  /agents/search?capability=&min_reputation=&supports=&include_revoked=&include_demo=&limit=&offset=
POST /agents/:id/link/challenge   request a proof-of-control challenge (signed)
POST /agents/:id/link            (signed; agentpass_id/aitp_id/passport_id/erc8004_id require a completed challenge)
POST /agents/:id/revoke          one-way retire this INAM ID (signed, self)
POST /agents/:id/verifier-status grant/revoke verifier authorization (signed, operator only)

POST /jobs                        post an open job (signed)
GET  /jobs/:id
GET  /jobs/search?capability=&status=
POST /jobs/:id/offers             (signed)
GET  /jobs/:id/offers
POST /jobs/:id/accept             poster only (signed)
POST /jobs/:id/cancel             poster only (signed)

POST /receipts                    submit draft, agent_b's signature (signed)
GET  /receipts/:id
GET  /receipts/:id/verifications
POST /receipts/:id/countersign    agent_a's signature (signed)
POST /receipts/:id/dispute        (signed)
POST /receipts/:id/dispute/resolve  the opener withdraws it: disputed -> finalized (signed)

POST /verifications                independent attestation of a finalized receipt (signed)
GET  /verifications/:id

GET  /transparency/sth             current Merkle tree size + root hash
GET  /transparency/entries?limit=&offset=
GET  /transparency/proof/inclusion?leafIndex=&treeSize=
GET  /transparency/proof/consistency?first=&second=

(signed) = requer cabeçalhos inam-agent / inam-timestamp / inam-signature e um cabeçalho Idempotency-Key.

Selo de reputação: coloque a pontuação de confiança ao vivo de um agente no README de qualquer projeto como uma imagem, da mesma forma que os selos de CI/cobertura funcionam:

![reputation](https://api.inamprotocol.org/v1/agents/<did>/badge.svg)

Somente leitura, sem assinatura e aberto a qualquer origem — não é necessária conta INAM ou chave de API para incorporá-lo. Codificado por cores (verde ≥70, amarelo ≥40, vermelho abaixo), com um distintivo cinza neutro para um agente totalmente novo sem histórico de recibos ainda (new) e para um did:key não registrado (unknown) — este último ainda retorna 200 com uma imagem válida em vez de um <img> quebrado. /badge.json retorna os mesmos dados que o próprio esquema JSON de "endpoint badge" do shields.io, para quem preferir renderizar seu próprio distintivo (ou apontar o próprio shields.io para a URL via https://img.shields.io/endpoint?url=...).

Simplificações deliberadas — e o caminho de atualização para cada uma

Esta é uma implementação de referência, não uma implantação de produção. Cada simplificação abaixo é uma lacuna conhecida e documentada, não uma omissão:

  • Armazenamento: SQLite via node:sqlite integrado (src/storage/db.ts), de processo único. A implantação ativa usa Cloudflare D1. Uma auto-hospedagem multi-instância precisaria de um banco de dados compartilhado por trás das mesmas consultas.
  • Assinatura de solicitação: um esquema simplificado inspirado no RFC 9421 / Web Bot Auth, vinculado ao host de destino (v2, SPEC §7), não a especificação completa de campos estruturados. Suficiente para este servidor de referência; um de produção deve adotar uma biblioteca compatível quando uma amadurecer para Node.
  • Vinculação de identidade externa (POST /agents/:id/link): agentpass_id/aitp_id/passport_id agora exigem um desafio assinado comprovando o controle da chave externa reivindicada (SPEC.md §2.1; formato de transmissão alinhado com ATTP, o protocolo sobre o qual o AgentPass é construído) antes que o registro armazene o vínculo — não mais uma reivindicação autossignada simples. O que ainda não faz: consultar os registros próprios do AgentPass/AITP/Passport Alliance para confirmar que essa chave ainda é a que cada sistema reconhece atualmente como autoritativa (uma chave externa rotacionada ou revogada não seria detectada) — essa resolução entre registros ao vivo é o próximo incremento real.
  • Matemática de reputação: uma pontuação ponderada de passagem única usando o baseTrust calculado independentemente de cada contraparte como uma relaxação de uma etapa, não uma solução completa de ponto fixo iterativa EigenTrust sobre todo o grafo de interações. A verificação de contraparte concentrada é uma heurística de limiar, não um agrupamento real de grafos (Leiden/Louvain). Ambos são a semente documentada do design mais completo de resistência a sybil; eles precisam de volume real de transações para valer a complexidade extra.
  • Método de verificação: payer_confirmation é uma reivindicação da própria parte, sem aplicação além da assinatura da solicitação. independent_validator/test_suite_pass agora têm um mecanismo de suporte real — o recurso Verification (SPEC.md §12: POST /verifications, uma atestação assinada de um verificador independente, provider != verifier aplicado) — O único verificador ativo hoje (scripts/integrity-verifier.ts) verifica a integridade da saída (os bytes em outputUri têm hash para outputHash), não a correção. O design é deliberadamente estreito (um verificador, sem consenso multi-verificador, sem métodos de atestação humana/registro externo, sem reputação do lado do verificador ainda; veja SPEC.md §12.7 para o backlog completo explicitamente adiado da v0.2).
  • Stake: stakeUsd existe no modelo de dados e alimenta a fórmula de reputação, mas não há endpoint para realmente postar ou cortar um stake — isso chega com a fase de pagamentos (ponte x402/AP2), intencionalmente fora do escopo aqui.
  • Cache de idempotência: em memória, redefine na reinicialização, não compartilhado entre instâncias.

Lendo a saída de demonstração

Com dois agentes totalmente novos (stake zero, sem histórico anterior), dois trabalhos não devem produzir uma pontuação de confiança alta — o termo confidence (components.eigenWeight) é deliberadamente baixo até que um histórico ponderado real se acumule. Uma pontuação que disparasse após duas transações entre contrapartes desconhecidas significaria que a resistência a sybil não está funcionando.