agentgate

Evidência somente leitura das ferramentas que os agentes executam: o registro de um servidor MCP, quais scanners realmente rodaram e verificações de política. Registros incompletos nunca são considerados limpos.

Documentação

Português (Brasil) · 中文

agentgate

Um plano de controle para as ferramentas que os agentes executam. Ele inventaria o que está em uso, registra as evidências por trás de cada afirmação, declara o que uma empresa recusa e aplica essa decisão na CI e em tempo de execução.

Todo o projeto segue uma regra:

clean é emitido somente quando todas as verificações foram executadas. Qualquer coisa que não pôde ser medida é unmeasured, e um artefato com uma parte não medida é incomplete — nunca clean.

Essa regra existe porque a falha usual de um scanner de segurança é um build verde para trabalho que ninguém fez. Aqui, uma verificação que falha torna o resultado incompleto, então isso não pode acontecer silenciosamente.

As quatro partes

parteo que fazpacote
inventárioenumera o registro, resolve pacotes, busca repositóriospackages/collect
evidênciajunta tudo em um registro por servidor, com os bytes por trás de cada afirmaçãopackages/collect
políticaverifica configurações, hooks, manifestos e código-fonte para o que uma empresa recusariapackages/guard
verificaçãoconfere uma afirmação contra algo externo à afirmaçãopackages/verify

Executando

A configuração do servidor está em docs/operations/deployment-runbook.md. O primeiro deploy, em 2026-09-16, está documentado em docs/verification.md junto com o que foi verificado e o que ainda não foi.

docs/capabilities.md lista o que este projeto pode e não pode afirmar, uma linha cada, cada linha carregando um comando que você pode executar. Ele existe porque um consultor uma vez escreveu nossas capacidades para nós e incluiu quatro que não temos.

Experimente sem instalar

O serviço roda em https://xn--5kvo87g.com/: página inicial, preços, o índice de evidências (reconstruído diariamente) e a API no mesmo host.

https://ciceroyang.github.io/agentgate/ é a página inicial no GitHub Pages. O índice é uma única página navegável em https://ciceroyang.github.io/agentgate/evidence.html, reconstruída diariamente a partir do registro ao vivo — os registros são incorporados, a filtragem acontece localmente e não há nada para se cadastrar. Preços e um passo a passo de dez minutos.

Início rápido

Atualizando para 0.6.0: leia o guia de atualização antes de substituir um gate de admissão existente ou uma instalação de watch. O pacote 0.5.0 pode aprovar incorretamente um gate de evidência obrigatória quando a evidência está ausente; não o use para um novo gate. Confirme a versão que você instalou e veja o registro de versão para verificação de pacote público. Um checkout do código-fonte e o serviço hospedado podem executar versões diferentes.

Node 20 ou mais recente, sem dependências. Um clone já carrega um índice de exemplo, então o serviço responde imediatamente; refresh o substitui por um atual.

node bin/agentgate.mjs serve
# agentgate serving http://127.0.0.1:8080

curl -s localhost:8080/health
curl -s localhost:8080/v1/index/summary
curl -s localhost:8080/v1/servers/<name>
curl -s localhost:8080/badge/<name>.svg

O pacote está no npm como @zhiliangtech/agentgate. Envie uma tag v* e a CI o publica com proveniência; publish-checklist.md tem a configuração e o registro do que foi verificado.

npx --yes --ignore-scripts @zhiliangtech/agentgate@0.6.0 check --root .
npx --yes --ignore-scripts @zhiliangtech/agentgate@0.6.0 serve

Um comando npx sem versão segue a dist-tag latest, não este checkout. Fixe a versão aceita; editar um número de versão local não altera o pacote público.

Sem arquivo de política, check usa um padrão embutido que não recusa nada extra, e serve responde a partir do snapshot que o pacote veio com. refresh grava em ./data ao seu lado, nunca dentro do pacote instalado.

Docker também funciona e executa o mesmo comando:

docker compose up                            # the service on :8080
docker compose --profile collect run --rm refresh   # rebuild data/index.json and seed the first snapshot

Inventário de ferramentas

Execute node bin/agentgate.mjs serve e abra /inventory.html no endereço que ele imprimir. Cole uma lista de nomes de ferramentas ou escolha um arquivo de texto/JSON, resolva correspondências ambíguas, preencha a versão que você realmente usa e baixe um relatório HTML autônomo. A comparação acontece na memória do navegador contra o snapshot do índice incorporado: a lista não é enviada ou armazenada, sua máquina não é verificada e nenhuma ferramenta é executada. Quando um registro carrega um bloco de cobertura, o relatório também lista quais scanners foram executados e quais não foram, e por quê; um registro cujo bloco de cobertura próprio diz que um scanner obrigatório não terminou não será mostrado como correspondente, por mais completa que o resto de sua evidência pareça.

A mesma coisa sem navegador:

node bin/agentgate.mjs inventory --input examples/inventory/tools.json --out my-tools.html
node bin/agentgate.mjs inventory --input tools.json --index data/index.json --format json

Uma entrada é um nome por linha, um array JSON ou { "tools": [...] }. Cada objeto pode carregar name, server, package, registry e version — nada mais. Configurações completas de cliente e credenciais são rejeitadas de propósito. O guia de inventário tem os detalhes.

Itens sem correspondência, ambíguos, sem versão, com versão incompatível e com evidência incompleta permanecem no relatório. Uma correspondência de versão não é prova do que está instalado. O exemplo commitado é histórico e não pode produzir uma correspondência confirmada; evidências antigas sem um vínculo de conteúdo exato também não podem. Mesmo uma correspondência confirmada não é uma certificação de segurança e não é uma nova verificação. Olhe para os escopos, os achados, a data do snapshot e as lacunas antes de confiar nisso.

Código de saída 0 significa que um relatório foi produzido, não que todas as ferramentas passaram. Entrada malformada ou dados ilegíveis saem com 2, e --out não sobrescreverá um arquivo existente. Quando você quiser que a CI recuse algo, use check, não inventory.

Obtendo a lista em primeiro lugar

Ninguém tem essa lista manualmente. discover lê os arquivos de configuração MCP já na máquina e produz entrada que inventory --input aceita. Ele imprime coordenadas de pacote como linhas quando todas as identidades exportadas são conhecidas; se alguma entrada for somente alias, ele usa JSON para que um alias como tool@1.2.3 não possa ser confundido com um pacote e versão verificados:

node bin/agentgate.mjs discover --out tools.txt          # home directory + current directory
node bin/agentgate.mjs discover --roots ~/code/a,~/code/b --format json

Ele nunca imprime um valor env, um cabeçalho ou um argumento, e um endereço remoto é reduzido ao seu host, porque caminhos e strings de consulta carregam tokens. Ele lê as tabelas MCP .codex/config.toml do Codex sem iniciar os servidores configurados. Entradas explicitamente desabilitadas permanecem visíveis em --format json, mas são omitidas das exportações de texto e inventário. Formas TOML MCP não suportadas, arquivos malformados e arquivos ilegíveis são listados com um motivo e fazem o comando sair com 2. Nomes de pacotes e versões são obtidos apenas de argumentos de runner declarados reconhecíveis; um comando personalizado ou host remoto não é tratado como um pacote ou versão de runtime verificados.

Vários repositórios

node bin/agentgate.mjs audit --roots ~/code/a,~/code/b,~/code/c --index data/index.json

Uma verificação por diretório, um veredito para o conjunto. Qualquer diretório incompleto torna a auditoria incompleta, e um diretório que não existe conta como não medido em vez de ignorado.

Mudanças desde a última vez

node bin/agentgate.mjs watch --input tools.txt --index data/index.json --archive ./archive
node bin/agentgate.mjs watch --verify --archive ./archive
node bin/agentgate.mjs watch --input tools.txt --index data/index.json --archive ./archive \
  --webhook https://example.invalid/hook --webhook-format wecom

Cada execução anexa uma linha a um arquivo encadeado (prev é o hash da linha anterior) e armazena o que viu sob snapshots/<sha256>.json. --verify recalcula a cadeia e cada snapshot retido, e sai com 1 se algo não corresponder. Nada é enviado a lugar algum a menos que --webhook nomeie um endereço, e o arquivo é gravado antes do push, então um serviço de chat fora do ar não pode perder uma captura.

Mapeamento de questionário

node bin/agentgate.mjs framework                       # who answers which AI-CAIQ item
node bin/agentgate.mjs inventory --input tools.json --framework aicaiq --out report.html

Para cada item do AI-CAIQ, o mapeamento diz o que podemos fornecer, onde nossa cobertura termina e se a resposta é nossa, do cliente ou de um avaliador independente. Ele descreve evidências. Não é uma conclusão de conformidade e não reproduz o texto oficial. Todos os 58 itens dos quatro domínios que um revisor pergunta a um fornecedor são classificados: 13 respostas são nossas, 41 são do cliente e 4 precisam de um avaliador independente.

Pacote de evidências

O mapeamento diz o que podemos fornecer. pack produz a coisa em si: um diretório que um fornecedor entrega à pessoa que o revisa, onde cada resposta que afirmamos aponta para evidências no mesmo diretório e tudo o que não pudemos medir é contado no topo.

node bin/agentgate.mjs pack --input tools.json --archive ./agentgate-archive --out agentgate-pack
node bin/agentgate.mjs pack --verify agentgate-pack     # recompute every hash and the seal

Ele grava pack.json (legível por máquina), pack.html (para o revisor), answers.aicaiq.md (todos os 58 itens, cada um classificado), manifest.txt (um sha256 por arquivo) e manifest.sha256 (o selo no manifesto). Uma resposta cuja evidência está ausente lê unmeasured e o comando sai com 2, não 0. Exemplo construído a partir do índice ao vivo: docs/samples/evidence-pack-example — verificável com pack --verify. Contrato: docs/spec/evidence-pack-v1.md.

Servidor MCP

Qualquer coisa que fale MCP pode consultar o índice diretamente. Adicione isso a claude_desktop_config.json, um .mcp.json de repositório, ou o que seu cliente ler:

{
  "mcpServers": {
    "agentgate": { "command": "npx", "args": ["--yes", "@zhiliangtech/agentgate@next", "mcp"] }
  }
}

Quatro ferramentas somente leitura: lookup_server (um registro, com seu bloco de cobertura), inventory_tools (corresponda às ferramentas que você realmente usa), coverage_report (quanto do índice foi medido) e check_project (verifique um diretório local). Ele lê o índice local, nunca grava, nunca envia, e nunca executa uma ferramenta verificada. Um registro incompleto é relatado como incompleto, e um registro que o índice não tem é relatado como ausente em vez de seguro. Detalhes: docs/spec/mcp-server-v1.md.

Política

Uma política declara o que uma empresa recusa. É dado em vez de código, e tem uma especificação: docs/spec/policy-v1.md.

{
  "version": "agentgate.policy/v1",
  "threshold": "high",
  "required": { "pinnedPackages": true, "measuredEvidence": ["packageManifest"] },
  "forbidden": { "rules": ["AG-INSTALL-001"], "servers": ["internal/*"] }
}
node bin/agentgate.mjs check --policy agentgate.policy.json --root . --index data/index.json

A política acima exige evidência indexada. Forneça um índice real correspondente ao nome e versão exatos do pacote npm local: evidência ausente sai com 2; um índice explicitamente ausente, malformado ou de exemplo sai com 3. Uma verificação de código-fonte local não substitui a evidência de pacote obrigatória.

Sem arquivo de política e sem --policy, a verificação ainda é executada. Ela relata o que as verificações encontraram e diz que usou o padrão embutido, que não recusa nada extra; inventar obrigações em seu nome tornaria o resultado menos significativo, não mais. Uma política que você nomeia explicitamente e que não pode ser lida é um erro, porque isso é um erro de digitação.

A mesma avaliação pode ir para uma pessoa em vez de um terminal:

node bin/agentgate.mjs check --policy agentgate.policy.json --root . --index data/index.json --format html --out report.html

Um arquivo estático e imprimível sem script nele. Qualquer coisa que não pôde ser medida ganha sua própria seção acima dos achados: um relatório que enterra o que não verificou parece mais completo do que é. Este arquivo é o que a verificação gratuita entrega.

Há três resultados, e incomplete supera findings. Se uma verificação falhou ao executar, ou um bloco de evidência que a política exige é unmeasured, o código de saída é 2 por mais limpos que os achados pareçam. Nenhum limite transforma uma resposta parcial em aprovação.

saídasignificado
0limpo
1achados
2incompleto

Aplicação

Um pull request que adiciona algo que a política recusa não será mesclado, e o motivo é postado no pull request em vez de deixado em um log que ninguém abre.

- uses: ciceroyang/agentgate@main
  with:
    policy: agentgate.policy.json
    index: data/index.json

Veja examples/github-actions/policy.yml. A ação executa a verificação, grava SARIF para code scanning, comenta o relatório no pull request e sai com o próprio código da verificação — então uma verificação incompleta ainda falha o build com 2.

Tempo de execução

A mesma política pode se aplicar ao que já foi enviado, se você colocar um gateway na frente do servidor em vez de apontar seu cliente para ele:

node bin/agentgate.mjs proxy --policy agentgate.policy.json --log calls.jsonl -- \
  npx -y @modelcontextprotocol/server-filesystem /data

Uma chamada que a política recusa é respondida localmente com um motivo e nunca chega ao servidor. Uma ferramenta proibida é removida da lista anunciada, então um cliente não pode pedi-la de forma alguma. Cada decisão, permitida ou recusada, é anexada ao log.

Histórico

O índice é mantido, então dois builds podem ser comparados. A coluna interessante é a última: mudanças que uma versão teria explicado e não explicou.

node bin/agentgate.mjs diff --from previous-index.json --to data/index.json
  added:           0
  removed:         0
  verdict changed: 1
  package changed: 0
  silent (no version move, different evidence): 1

Um novo achado em uma versão inalterada geralmente significa que um pacote foi substituído sem uma versão, um repositório foi editado no lugar, ou a verificação começou a ver algo. Esse registro não pode ser preenchido retroativamente. Ele só existe se alguém estava olhando na época.

Os pipelines por trás do índice

node packages/collect/mcp-audit.mjs --max 6000 --out data/census.json
node packages/collect/scripts/guard-scan.mjs --census data/census.json --out data/guard-scan.json
node packages/collect/scripts/build-index.mjs --census data/census.json --guard data/guard-scan.json --out data/index.json
node scripts/coverage-stats.mjs --index data/index.json   # how much of it was actually measured

E o scanner em um projeto local:

node packages/guard/bin/agent-guard.mjs . --fail-on high
node packages/collect/bin/agent-add.mjs --index data/index.json <server-name>

Escrevendo

Teste

npm test                              # the whole suite; it prints how many ran
node scripts/bench.mjs 50000 200      # lookups must stay under 10 ms p50
node scripts/measure-verify.mjs       # claim extraction, against a small labelled set
node packages/guard/scripts/regression.mjs   # benign must stay silent, positives must fire

Layout

packages/guard     the scanner: engine, nine checks, CLI, corpus, GitHub Action
packages/collect   census, package and repository scanning, the evidence index
packages/policy    policy evaluation and human-readable reports
packages/gateway   runtime policy enforcement for MCP servers over stdio
packages/history   index snapshots and change comparisons
packages/service   the read-only evidence API
packages/verify    cross-model claim checking
docs/              architecture and product notes

Verificação

Os testes são escritos pelas mesmas pessoas que escreveram o código. docs/verification.md registra as verificações que não são: um servidor MCP real através do gateway e a lista do que ainda não foi verificado.

node scripts/verify-real-server.mjs

Para ver se as descobertas de high e critical do índice ainda correspondem às revisões humanas registradas, execute node scripts/review-criticals.mjs. Uma revisão precisa vincular a descoberta e suas evidências a uma versão exata do pacote e à proveniência completa do conteúdo verificado, incluindo o digest SHA-256 e o escopo. Um vínculo ausente ou alterado exige outra revisão humana, e aprovações legadas não são atualizadas automaticamente. --accept registra uma revisão que já ocorreu e recusa proveniência incompleta; ela não realiza a revisão nem certifica código de terceiros.

Operações

Status

Este é um núcleo de código aberto em estágio inicial. Ele cobre coleta, um índice de evidências, varredura, verificações de política no CI, um gateway de runtime para servidores MCP via stdio, diffs históricos e um serviço somente leitura. Scripts de implantação e um runbook estão na árvore, e a primeira implantação com suas verificações está documentada em docs/verification.md. Esse documento não diz nada sobre a saúde atual do serviço hospedado. O caminho do contêiner não é afirmado, mas construído: o CI executa docker compose up --build e depois uma verificação de saúde contra o contêiner em execução.

O que os identificadores de versão prometem e quais versões são suportadas está documentado em docs/spec/compatibility.md; SECURITY.md diz como relatar uma vulnerabilidade e o que esperar. Nenhum deles substitui as portas 3 e 4 acima — a superfície empresarial ainda está ausente e ninguém fora deste repositório depende dela ainda.

Os recursos empresariais descritos na proposta de preços — SSO/SAML, RBAC, multi-inquilinos e exportação de auditoria assinada — não estão implementados. Os preços de Equipe e Empresa são hipóteses não validadas; o piloto gratuito é como testamos se alguém quer isso. Veja o escopo do piloto e a licença.

Uma invariante está na suíte de testes: uma verificação que falha nunca pode produzir clean. Execute npm test para os números atuais; esta página não repete uma contagem de testes.

Licença

AGPL-3.0-only. Se você quiser oferecer um agentgate modificado como um serviço fechado sem publicar suas alterações — o caso que a AGPL não permite — uma licença comercial está disponível. Veja docs/product/licensing.md.