AGA MCP Server
Gobernanza criptográfica en tiempo de ejecución para agentes de IA. 20 herramientas. Artefactos de política sellados, medición continua, prueba a prueba de manipulaciones. Ed25519 + SHA-256.
Documentación
AGA - Artefactos de Gobernanza Atestiguados
Registros de decisión verificables para agentes de IA: cada decisión registrada de llamada a herramienta es un recibo firmado y encadenado por hash, exportado en paquetes de evidencia que un revisor puede verificar sin conexión contra el formato publicado. La verificación establece la integridad de los recibos presentes, no que cada acción fue registrada.
Estado: implementación de referencia publicada, antes de la validación piloto independiente. La puerta de enlace emite paquetes clásicos Ed25519-SHA256-JCS. El
@attested-intelligence/aga-verify@2.2.2CLI publicado verifica ese perfil clásico; en un paquete v2/híbrido reporta FALLIDO porque no implementa ese perfil. El paquete también expone un compuesto ML-DSA-65 + Ed25519 como perfil de biblioteca, yaga-proxy verifypuede verificarlo. Los verificadores de referencia tienen su propio comportamiento para perfiles no soportados. Estos son componentes diferentes, no un verificador intercambiable. La procedencia de la compilación se refiere a la compilación publicada; no es corrección en tiempo de ejecución ni una auditoría de seguridad externa.
Estado de ejecución. Desde 3.5.0, una medición solicitada después de que expire el TTL del artefacto activo lo mueve a TERMINATE;
delegate_to_subagenttambién se niega después de la expiración. Nada verifica el TTL según un cronograma, y el paquete exportado no registra esa transición. No degradar a la obsoleta 3.3.3 como ruta de evaluación. Desde 3.6.0,aga-proxyhonraAGA_GATEWAY_KEY/AGA_GATEWAY_KEY_FILE; el upstream stdio puede heredar esas variables. Lea los problemas conocidos yTHREAT_BOUNDARY.mdantes de cualquier evaluación en tiempo de ejecución.
# This package IS the AGA MCP server (TypeScript, runs over stdio). Use it from any MCP client:
npx -y @attested-intelligence/aga-mcp-server@3.6.2
Los ejemplos de ejecución a continuación identifican el paquete 3.6.2 observado, no una implementación de producción recién aprobada. Revise primero los problemas conocidos; se requiere una evaluación sintética aislada antes de considerar un piloto. Prefiera la ruta del verificador estático para la primera verificación.
Un SDK complementario de Python (aga-governance) está documentado en la sección SDK de Python a continuación.
Verifíquelo usted mismo (no confíe en nuestra palabra)
No tiene que aceptar nada de esto por fe. El repositorio incluye el verificador de referencia, los vectores canónicos y paquetes de muestra, para que pueda verificar uno sin conexión ahora mismo, sin red y sin devolución de llamada a nosotros:
git clone https://github.com/attestedintelligence/aga-mcp-server
cd aga-mcp-server
# A canonical SEP bundle verifies; a one-byte-tampered copy is rejected.
node aga-receipt-spec/verify/verify-sep.mjs fixtures/valid_minimal.json # OVERALL: VERIFIED (integrity only; no key pinned)
node aga-receipt-spec/verify/verify-sep.mjs fixtures/tampered.json # OVERALL: FAILED
El @attested-intelligence/aga-verify CLI publicado coincide en el corpus clásico probado tal como lo suministra el arnés. npm run conformance:cross-stack (primero: npm run build && npm --prefix independent-verifier run build) demuestra que seis configuraciones de verificador v1, que abarcan tres cadenas de herramientas independientes (JavaScript, Go y Python, incluida una ruta de solo stdlib, sin criptografía de terceros), coinciden en los 54 casos a nivel de objeto. Los cinco verificadores de análisis de archivos también coinciden en los 7 casos de análisis de bytes crudos/archivos (61 en total). El motor dentro del servidor es solo de biblioteca, recibe objetos analizados en lugar de bytes de archivo crudos, por lo que no ejecuta los casos de análisis de archivos; seis configuraciones no coinciden en los 61 y esto ya no afirma que lo hagan. npm run conformance:cross-stack-v2 demuestra que dos oráculos genuinamente independientes en lenguaje (@noble/JS y CIRCL/Go) coinciden en el corpus compuesto v2. Para una reproducción de fuente y compilación (compile el paquete usted mismo, reproduzca el tarball publicado byte por byte, vuelva a ejecutar cada compuerta), consulte REVIEWER_GUIDE.md (una ruta de autoservicio comando por comando), REPRODUCIBILITY.md y el paso a paso SKEPTICAL_AUDITOR.md. Esta versión incluye procedencia de compilación SLSA, verificable con npm audit signatures.
Qué Hace Esto
Esto está construido para equipos que envían productos de IA agéntica a servicios financieros y seguros, en el momento en que la revisión de riesgo de proveedor, riesgo de modelo o auditoría interna de un cliente pregunta qué hizo su agente y cómo alguien podría saberlo.
Las llamadas a herramientas cubiertas enrutadas a través de aga-proxy se evalúan contra su política configurada. Cada decisión registrada (PERMITIDO o DENEGADO) toma la forma de un recibo de gobernanza firmado y vinculado por hash; el problema conocido 7 a continuación describe llamadas rechazadas sin recibo. aga-proxy también firma el SHA-256 del JSON canónico de su política en cada recibo; consulte KNOWN_LIMITATIONS.md para saber qué vincula ese campo. Los recibos se recopilan en paquetes de evidencia que cualquiera que tenga el formato publicado y la clave pública puede verificar sin conexión, sin devolución de llamada a nosotros.
Registrar. Probar. Verificar.
Alcance: un paquete verificado demuestra la integridad de los recibos presentes: cada uno es auténtico, está correctamente ordenado, incluido en Merkle y (cuando se fija una clave) vinculado a la procedencia. No demuestra la no omisión (que cada acción que tomó el agente fue registrada); la integridad está limitada por la evidencia de manipulación del punto de intercepción, que está fuera del paquete. Consulte KNOWN_LIMITATIONS.md para el límite honesto completo, y THREAT_BOUNDARY.md para el detalle por campo.
Uso con Claude Desktop
Agregue a su configuración MCP de Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"aga": {
"command": "npx",
"args": ["-y", "@attested-intelligence/aga-mcp-server@3.6.2"]
}
}
}
Claude puede entonces sellar artefactos, medir integridad, generar paquetes de evidencia y verificarlos sin conexión a través de lenguaje natural.
Persistir la clave de firma (haga esto primero)
Por defecto, la puerta de enlace firma con una clave efímera que rota en cada reinicio. Eso está bien para una primera mirada, pero la procedencia del paquete de evidencia no se puede fijar entre reinicios (y el servidor advierte sobre ello en stderr). Establezca una semilla Ed25519 estable de 64 hex para que la procedencia siga siendo fijable:
Desde 3.6.0 esto aplica a ambos binarios.
aga-proxylee las mismas dos variables a través del mismo resolvedor e imprime la clave pública activa al inicio para que pueda fijarla fuera de banda;--ephemeralhace que una clave desechable sea una opción declarada. En 3.5.0 y anteriores,aga-proxyignoró ambas variables silenciosamente; una clave que estableció no tuvo efecto y no se imprimió ninguna advertencia, por lo que la evidencia de tal proxy es verificable en integridad pero no fijable en procedencia entre reinicios. ConsulteDEPLOYMENT.md§2.
# generate a seed once (32 random bytes, hex)
node -e "console.log(require('node:crypto').randomBytes(32).toString('hex'))"
Proporciónela a través de AGA_GATEWAY_KEY, o AGA_GATEWAY_KEY_FILE (una ruta a la semilla). En Claude Desktop, agregue un bloque env:
{
"mcpServers": {
"aga": {
"command": "npx",
"args": ["-y", "@attested-intelligence/aga-mcp-server@3.6.2"],
"env": { "AGA_GATEWAY_KEY": "<your-64-hex-seed>" }
}
}
}
Mantenga la semilla en secreto y fuera del control de versiones; consulte DEPLOYMENT.md para el manejo de claves. Una semilla en el entorno de un cliente agente no es un dominio de confianza separado, y el upstream stdio puede heredar las variables relacionadas con la clave (problema conocido 3). Los reinicios con la misma clave no preservan el libro mayor en memoria: exporte y verifique antes de detener.
Herramientas MCP (15)
| Categoría | Herramientas |
|---|---|
| Identidad | get_server_info, get_portal_state |
| Ciclo de vida | init_chain, attest_subject, revoke_artifact |
| Medición y decisión | measure_integrity, measure_behavior, verify_chain |
| Evidencia | generate_evidence_bundle, verify_bundle_offline |
| Privacidad | request_claim, list_claims |
| Delegación | delegate_to_subagent |
| Auditoría | get_receipts, get_chain_events |
measure_behaviores solo detective por defecto: observa patrones de uso de herramientas y registra un hallazgo de deriva firmado y demostrable, pero no bloquea. La aplicación (deriva → cuarentena) es opcional a través deenforce=truey está desactivada por defecto. Las decisiones duras de gobernanza (PERMITIDO/DENEGADO) las toma el portal/PEP, no el monitor de comportamiento.
Inicio rápido: verificar un paquete sin conexión
Un paquete que este paquete emite (a través de la herramienta MCP generate_evidence_bundle) es un paquete SEP canónico. Verifíquelo sin conexión, sin red y sin devolución de llamada a nosotros:
# Published verifier CLI. Obtain and authenticate the expected key outside the bundle before running.
npx -y @attested-intelligence/aga-verify@2.2.2 evidence-bundle.json --pubkey <gateway-public-key>
# Or, from a clone of this repo, the zero-dependency reference verifier (Node 18+) checks its supported profile; parser/pin behavior can differ:
node aga-receipt-spec/verify/verify-sep.mjs evidence-bundle.json --pubkey <gateway-public-key>
El @attested-intelligence/aga-verify CLI publicado es la ruta enviada (el antiguo 1.0.0 falsificable está obsoleto); el verify-sep.mjs de referencia proporciona otra implementación desde un clon del repositorio; el acuerdo de veredicto se limita a los casos probados, no a todos los bytes de entrada. Sin --pubkey obtiene un resultado solo de integridad (issuerVerified=false); proporcione una clave esperada no vacía desde un canal confiable separado para autenticar esa clave de firma; el mapeo a una organización depende de ese canal. Un --pubkey final sin valor vuelve al éxito solo de integridad en 2.2.2. Consulte THREAT_BOUNDARY.md §3.7. Un verificador de navegador alojado está vinculado bajo Enlaces.
El algoritmo de referencia §6 está implementado en tres lenguajes: JavaScript (aga-receipt-spec/verify/verify-sep.mjs), Go (verify.go, stdlib crypto/ed25519) y Python (verify.py, Ed25519 RFC-8032 de solo stdlib). Un arnés de pila cruzada (npm run conformance:cross-stack; primero: npm run build && npm --prefix independent-verifier run build) demuestra que los tres, más el motor dentro del servidor y aga-verify, coinciden en los casos canónicos publicados tal como los alimenta el arnés (los casos de objeto se re-serializan; los casos de bytes crudos son separados). Fuera de ese corpus, las implementaciones difieren, incluida alguna semántica de analizador y fijación. El perfil compuesto v2 (ML-DSA-65+Ed25519-SHA256-JCS) se mantiene al mismo nivel por un segundo arnés (npm run conformance:cross-stack-v2): un motor @noble/JavaScript y un oráculo CIRCL/Go, dos cadenas de herramientas genuinamente independientes, producen veredictos idénticos en el corpus v2 fijado, y el verificador v1 de referencia (verify-sep.mjs/verify.py/verify.go) devuelve UNSUPPORTED_PROFILE (salida 3) en un paquete v2, señalando "perfil no implementado" en lugar de un "inválido" engañoso. (El aga-verify CLI publicado no implementa esta tricotomía de perfil: en un paquete v2 devuelve FALLIDO (salida 1). Use la salida 3 como señal de perfil no soportado solo con los verificadores de referencia.)
Mapeo de nombres de verificación entre implementaciones
El verificador de referencia JS y el SDK de Python (aga-governance) descomponen la misma verificación de siete comprobaciones de manera diferente. Los veredictos generales y los códigos de salida coinciden en los 61 casos del corpus de conformidad tal como los alimenta el arnés de pila cruzada (casos a nivel de objeto re-serializados, por lo que las grafías de flotantes llegan como enteros; medido en aga-governance 0.3.2 el 2026-09-25) y en las 10 celdas re-probadas el 2026-07-01 (paquetes prístinos y manipulados con claves no fijadas, correctas e incorrectas). En los bytes de archivo literales del caso leaf_index con grafía de flotante del corpus (0.0), aga-governance 0.3.2 reporta FALLIDO donde la referencia JS, aga-verify, Go y los verificadores de referencia de Python reportan VERIFICADO; consulte https://attestedintelligence.com/spec. La subverificación que reporta una manipulación dada puede diferir:
| Verificación de referencia JS | Campo de resultado de Python | Qué cubre |
|---|---|---|
structural | algorithm_valid + partes de bundle_consistent | id de algoritmo, buena formación de clave, conteos de recibo/prueba |
receipt_signatures | receipt_signatures_valid | Ed25519 sobre bytes de recibo canónicos |
chain_and_ordering | chain_integrity_valid | enlace de hoja anterior, marcas de tiempo canónicas no decrecientes (los ids no son campos de orden y no se verifican) |
merkle_and_bijection | merkle_proofs_valid | recálculo de hoja, recorrido de raíz única, biyección de índice |
signed_checkpoint | checkpoint_valid | raíz firmada por puerta de enlace + conteo + enlace de cabeza de cadena |
envelope_consistency | envelope_consistent | sobre gateway_id, generated_at, merkle_root vs contenido firmado (bundle_id, schema_version, el sobre policy_reference y offline_capable no están firmados y no se verifican) |
gateway_key_match (con --pubkey) | gateway_key_match / provenance | clave de emisor fijada |
Diferencia de descomposición conocida: la referencia JS recalcula cada hoja Merkle a partir del contenido completo del recibo, por lo que una manipulación de la firma del recibo también falla en merkle_and_bijection; el verificador Python expone la misma manipulación en receipt_signatures_valid, chain_integrity_valid y bundle_consistent mientras que su merkle_proofs_valid puede permanecer verdadero. Ninguno es más laxo: el paquete falla en ambas pilas, salida 1. Un --pubkey KEY que no sean 64 caracteres hexadecimales en minúsculas es un error de uso (salida 2) en la referencia JS, aga-verify y el SDK de Python, y un pin de 64 hexadecimales que no sea un punto de curva válido se honra, falla al coincidir y hace fallar el paquete (salida 1). Escrito como --pubkey=KEY, el pin es ignorado por la referencia JS, aga-verify, verify.go y v2/verify-v2.go, y por verify.py cuando sigue la ruta del paquete (solo integridad, salida 0), y es leído por el SDK de Python. Otros verificadores también difieren. El motor dentro del servidor (la exportación ./verify del paquete, que verify_bundle_offline llama) trata un pin que no sea una clave bien formada para el perfil del paquete (para un paquete v1, un punto de orden pequeño o una codificación no canónica) como ausencia de pin, y devuelve VERIFIED con pinned: false. v2/verify-v2.go hace lo mismo e imprime integrity only; no key pinned (salida 0). Un valor de 64 hexadecimales que no sea un punto de curva cuenta como bien formado, por lo que ambos lo toman como pin y el paquete falla. Los verificadores de referencia Go y Python en aga-receipt-spec/verify/ tratan un pin que no sean 64 hexadecimales en minúsculas de la misma manera e imprimen integrity only; no key pinned (salida 0). Lea pinned antes de tomar un VERIFIED como procedencia; en CI, pase la clave después de un espacio y verifique que la salida diga procedencia verificada. Un --pubkey dado sin valor también se trata como ausencia de pin (salida 0, solo integridad) por aga-verify, verify-sep.mjs, verify.py, verify.go y v2/verify-v2.go, y es un error de uso en el SDK de Python. Otras diferencias conciernen al paquete más que al pin, y https://attestedintelligence.com/security enumera las medidas, incluyendo qué etiquetas de algoritmo deja cada verificador sin comprobar; fuera del corpus de conformidad, los verificadores difieren en ambas direcciones. Dos ejemplos, donde el lado que falla cierra de forma segura: una prueba leaf_index escrita como un flotante integral (1.0) reporta FAILED en aga-governance 0.3.2 y VERIFIED en los demás, y las claves de objeto fuera del Plano Multilingüe Básico (posible solo en un valor de campo no cadena, que ningún productor enviado emite) se ordenan de manera diferente en verify.py, verify.go, v2/verify-v2.go y aga-governance que en los verificadores JavaScript, por lo que tal paquete reporta VERIFIED en JavaScript y FAILED en Go y Python. Estos esperan la próxima revisión publicada.
Cómo Funciona
AI Agent AGA Proxy Verifier
| | |
|-- tools/call ----------->| |
| [Evaluate Policy] |
| [Sign Receipt] |
| [Chain to Previous] |
|<-- PERMITTED/DENIED -----| |
| | |
| [Export Bundle] |
| |--------- evidence.json ----->|
| | [Verify Signatures]
| | [Verify Chain + Order]
| | [Verify Merkle Tree]
| | [Verify Signed Checkpoint]
| | [PASS / FAIL]
Proxy de Gobernanza MCP
Ejecute AGA como un proxy frente a un servidor MCP que inicia como un proceso hijo stdio (el transporte stdio predeterminado), o uno al que llega con un POST JSON-RPC simple (--upstream-url; sin sesión Streamable HTTP ni manejo SSE). El puerto de agente del proxy habla JSON-RPC 2.0 delimitado por nueva línea sobre TCP crudo, no stdio ni Streamable HTTP. Un cliente MCP stdio necesita un relé que usted proporcione (unas pocas líneas que canalicen stdin al puerto y el puerto a stdout); no se incluye ninguno. Un cliente con script puede hablar ese marco directamente. Cada solicitud tools/call con un nombre de herramienta de cadena no vacío y argumentos que el proxy pueda canonizar se evalúa contra la política y produce un recibo firmado, excepto las llamadas que el problema conocido 7 a continuación describe como rechazadas sin uno. Otros métodos que no son benignos se reenvían con un recibo de paso firmado y no se evalúan por política, y los métodos de protocolo benignos (initialize, initialized, ping, tools/list, prompts/list, resources/list, resources/templates/list, logging/setLevel, completion/complete y notifications/*) no producen recibo (THREAT_BOUNDARY.md sección 3 elemento 2). Lea los problemas conocidos a continuación antes de exponer el puerto.
# Start the proxy (the `aga-proxy` bin) in front of an upstream MCP server.
# stdio upstream = the default stdio transport (the upstream is a child process, not network-reachable).
npx -p @attested-intelligence/aga-mcp-server@3.6.2 aga-proxy start \
--upstream "npx -y @modelcontextprotocol/server-filesystem /tmp/test" --profile permissive
permissive registra cada tools/call que evalúa (el problema conocido 7 describe las excepciones) y no deniega nada por motivos de política. standard y restrictive permiten solo nombres de herramientas de ejemplo genéricos, por lo que deniegan cada herramienta que este servidor de ejemplo expone; para permitir algunas de las herramientas de su servidor y denegar el resto, pase un archivo --policy que las nombre.
Exportando el paquete de evidencia desde un proxy en ejecución
El proxy registra recibos en su propio proceso y mantiene el libro mayor SEP en memoria. Para hacer que ese libro mayor en vivo sea accesible desde un shell separado, aga-proxy start abre un canal de control solo de loopback: un listener HTTP vinculado a 127.0.0.1 (nunca una interfaz enrutable), en su propio puerto (predeterminado 18801, anule con --control-port), distinto del puerto de proxy orientado al agente (18800). Expone solo rutas de lectura (/export, /status, /receipts); nada en él muta política o estado. No verifica el encabezado Host u Origin de una solicitud, por lo que una página web en un navegador en el mismo host puede leer sus respuestas a través de DNS rebinding a menos que el navegador lo bloquee (problema conocido 12). El proxy escribe el puerto de control elegido en ~/.aga-proxy/control.json junto a proxy.pid.
Una invocación separada de aga-proxy export lee ese archivo y obtiene el mismo paquete firmado que el proxy en ejecución emitiría:
# Terminal A: start the proxy in front of an upstream MCP server
npx -p @attested-intelligence/aga-mcp-server@3.6.2 aga-proxy start \
--upstream "npx -y @modelcontextprotocol/server-filesystem /tmp/test" --profile permissive
# (First, drive at least one tools/call through the proxy from your MCP client; an empty
# ledger has no receipts to checkpoint, and the export reports there is nothing to export.)
# Terminal B: export the live ledger from a different shell, then verify it offline
npx -p @attested-intelligence/aga-mcp-server@3.6.2 aga-proxy export -o evidence.json
npx -y @attested-intelligence/aga-verify@2.2.2 evidence.json --pubkey <gateway-public-key>
Exporte y verifique antes de detener el proxy: aga-proxy stop termina el proceso sin exportar, y la cadena en memoria se va con él (el problema conocido 9 cubre el tiempo de exportación y el límite de la cadena).
Si no hay ningún proxy en ejecución, aga-proxy export imprime no running proxy found; start it first, or export from within the session y sale con código no cero; nunca emite un paquete vacío o de marcador de posición. Dentro de la sesión del servidor MCP también puede llamar a la herramienta generate_evidence_bundle y guardar el JSON devuelto.
Libro mayor en memoria: el paquete exportado es el registro criptográfico duradero, pero la cadena en proceso en vivo no sobrevive a un reinicio del proxy. Este flujo hace que el libro mayor en vivo sea accesible desde otro proceso; no agrega persistencia entre reinicios, que necesita el backend persistente (SQLite) y sigue siendo hoja de ruta (ver KNOWN_LIMITATIONS.md).
El proxy intercepta solicitudes tools/call, las evalúa contra la política cargada (un archivo JSON o un perfil integrado; el SHA-256 de su JSON canónico se firma en cada recibo), y genera un recibo SEP firmado para cada decisión (excepto las llamadas que el problema conocido 7 a continuación describe como rechazadas sin uno). Las llamadas permitidas se reenvían al servidor descendente; las llamadas denegadas devuelven un error MCP y nunca lo alcanzan. Cada decisión está vinculada por hash y anclada a puntos de control en un paquete a prueba de manipulación. (Los métodos distintos de tools/call no se evalúan por política, pero los no benignos se registran como recibos de paso firmados para auditabilidad, y un llamador de biblioteca puede pasar una lista de denegación de métodos (denyMethods) para rechazarlos; el CLI aga-proxy no tiene bandera para ello; ver THREAT_BOUNDARY.md §3.2.)
Tres perfiles de política integrados:
- permisivo -
audit_only: no deniega nada por motivos de política y registra cadatools/callque evalúa (predeterminado); los rechazos de cierre seguro a continuación y el problema conocido 7 aún se aplican - estándar - una lista de permitidos de diez nombres de herramientas de ejemplo genéricos (
filesystem_read,shell_execute,web_searchy otros) con límites de tasa, y denegaciones por subcadena en dos de ellos; cada otra herramienta se deniega, por lo que las herramientas de un servidor real necesitan un archivo--policy - restrictivo - una lista de permitidos de tres nombres de herramientas de ejemplo genéricos con límites de tasa más bajos y un prefijo de ruta en uno; cada otra herramienta se deniega
Debido a que el predeterminado (permissive) es solo auditoría, comenzar con una política audit_only imprime un banner de stderr fuerte que indica que cada llamada está permitida y registrada y ninguna llamada se deniega en ese modo. Ninguna llamada se deniega por motivos de política, pero el proxy aún rechaza, con cierre seguro, un tools/call sin nombre de herramienta o con argumentos que no puede canonizar (anidados más allá de 100 niveles, por ejemplo), y firma un recibo DENIED para cada uno; un nombre de 0, false, null o una cadena vacía cuenta como sin nombre. La denegación por política necesita --profile standard o restrictive, o un archivo --policy en modo allowlist o denylist. En modo denylist, una política deniega cada herramienta que lista como un objeto cuyo valor allowed falta o es falso (false, 0, null o una cadena vacía); cualquier otro valor allowed permite la herramienta, incluida la cadena "false", y también una entrada listada que sea en sí misma false, 0, null o una cadena vacía en lugar de un objeto. En 3.6.0 a 3.6.2 también deniega una herramienta no listada nombrada como una propiedad de objeto integrada, como constructor. Aplica los límites de tasa de las herramientas listadas que permite; las reglas de ruta y patrón se aplican solo en modo allowlist y verifican solo argumentos de cadena de nivel superior (problema conocido 10). Un archivo --policy en modo audit_only permite cada llamada; uno con cualquier otro modo, o ninguno, deniega cada tools/call, y en 3.6.0 a 3.6.2 uno en modo allowlist o denylist cuyo miembro constraints falta o es nulo rechaza, sin recibo y sin respuesta, cada tools/call que tenga un nombre de herramienta y argumentos que el proxy pueda canonizar (problema conocido 7). Un valor --profile no reconocido es un error grave (salida 2 que lista los nombres válidos), nunca una caída silenciosa a permissive.
Verificación (SEP 3.0 canónico; algoritmo normativo §6 en aga-receipt-spec/verify/verify-sep.mjs)
- Piso estructural - El paquete declara Ed25519-SHA256-JCS, clave pública bien formada (todas las codificaciones de orden pequeño +
y ≥ pno canónico rechazado),receipts.length > 0, recuento de pruebas = recuento de recibos - Firmas de recibos - Ed25519 sobre JSON canónico de perfil JCS, clave ordenada (campo de firma excluido)
- Cadena + orden - El
previous_receipt_hashde cada recibo = hoja del recibo precedente; marcas de tiempo no decrecientes - Pruebas Merkle - Recalcular cada hoja a partir del contenido del recibo, recorrer hermanos/direcciones a una raíz, los índices de hoja forman la biyección completa
0..N-1 - Punto de control firmado - Verificar el punto de control firmado por la puerta de enlace que vincula
merkle_root,leaf_county la cabeza de la cadena (esto hace que la construcción sin prefijo sea segura contra truncamiento) - Procedencia (cuando una clave está fijada) -
public_key == expected key; de lo contrario, solo integridad se reporta
Primitivas Criptográficas
| Primitiva | Propósito |
|---|---|
| Ed25519 | Firmas de recibos |
| SHA-256 | Encadenamiento de hash, árboles Merkle, cálculo de hojas |
| Perfil JCS (JSON canónico de clave ordenada) | Firma determinista (canon es compatible con bytes con el verificador de referencia) |
| Árboles Merkle | Vinculación de todos los recibos a una sola raíz verificable |
Puerta de Enlace en Vivo
Una puerta de enlace de demostración está desplegada en Cloudflare Workers (un despliegue separado que puede rastrear su propia versión; trátelo como un espejo de conveniencia, y siempre verifique lo que devuelve fuera de línea contra una clave fijada, no como el artefacto canónico):
# Check status
curl https://aga-mcp-gateway.attested-intelligence.workers.dev/health
# Download a static demonstration bundle (not a live export)
curl https://attestedintelligence.com/sample-bundle.json -o evidence-bundle.json
# Static sample only. Use the separately published sample pin, not a key read from this file.
SDK de Python
Estado, verificado contra PyPI el 2026-09-28. La versión actual es
aga-governance0.3.2. La versión 0.3.1 corrigió el bloqueo de bomba de profundidad; 0.3.0 fue retirada por ese bloqueo. Ambos archivos 0.2.6 ahora también están retirados, pero eso no repara copias instaladas. Use la versión actual revisada al evaluar paquetes no confiables y retenga sus limitaciones documentadas de analizador y veredicto. El verificador de referencia JavaScript yaga-verifyno tienen ese bloqueo de bomba de profundidad de Python.
pip install "aga-governance==0.3.2"
from aga import AgentSession
with AgentSession(gateway_id="my-gateway") as session:
session.record_tool_call(
tool_name="search_web",
decision="PERMITTED",
reason="tool in allowlist",
request_id="req-1",
)
bundle = session.export_bundle()
result = session.verify()
assert result["overall_valid"]
Suite de Pruebas
Pruebas automatizadas en TypeScript y Python, más un corpus de conformidad:
- Servidor MCP TypeScript: 428 pruebas automatizadas (vitest), incluyendo regresiones de denegación demostrable y monitor de comportamiento
- Corpus de conformidad SEP:
npm run test:conformance(válido → VERIFICADO, negativos → FALLIDO) - SDK de Python complementario: el paquete PyPI
aga-governancepublicado por separado (instalado y verificado con smoke check aquí; su suite completa de pytest se ejecuta desde el árbol de fuentes). El smoke check importa el paquete e imprime su versión. No ejercita el verificador.
npm test # TypeScript tests (vitest)
npm run test:conformance # SEP conformance corpus
pip install "aga-governance==0.3.2" && python -c "import aga; print(aga.__version__)" # Python SDK smoke check
Benchmarks
La determinismo del formato de recibo es reproducible aquí: npm test ejecuta los vectores entre lenguajes, y npm run conformance:cross-stack (primero: npm run build && npm --prefix independent-verifier run build) muestra que las seis configuraciones del verificador v1 (en tres toolchains independientes: JS, Go, Python) coinciden en los 54 casos a nivel de objeto del corpus canónico de 61 casos. Los 7 restantes son casos de análisis de bytes crudos/archivos ejecutados por los cinco verificadores de análisis de archivos, ya que el motor dentro del servidor nunca recibe bytes crudos. npm run conformance:cross-stack-v2 muestra que los dos oráculos v2 en lenguajes independientes coinciden en el corpus compuesto.
Estructura del Proyecto
src/
sep/ # Canonical SEP evidence engine: single source of truth (canon, merkle, receipt, checkpoint, bundle, verify)
core/ # Governance primitives (portal, artifact, attestation, disclosure, delegation, behavioral) + internal continuity-chain profile
crypto/ # Internal continuity-chain crypto: Ed25519 (node:crypto), SHA-256/blake2b, salt
proxy/ # MCP governance proxy (transparent interception + policy evaluation; emits SEP bundles)
middleware/ # Governance PEP wrapper (records a signed PERMITTED/DENIED receipt per governed call)
independent-verifier/ # @attested-intelligence/aga-verify: standalone SEP verifier, zero AGA imports
scenarios/ # Demo scenarios (SCADA, autonomous vehicle, AI agent) that emit SEP bundles
tests/ # TypeScript test suite (428 automated tests)
Enlaces
- Sitio web
- Tecnología
- Verificador en vivo
- Confianza y alcance
- Materiales de diligencia
- Servidor MCP (npm)
- SDK de Python (PyPI)
- Registro de cambios
- Límite de amenazas
- Guía de despliegue
Problemas conocidos en 3.6.0 a 3.6.2 y los verificadores publicados
3.6.1 y 3.6.2 cambian solo la documentación y el número de versión; el runtime es el de 3.6.0. Los elementos 1 a 4 se reprodujeron el 2026-09-23 en @attested-intelligence/aga-mcp-server 3.6.0 instalado desde npm, y
conciernen a la puerta de enlace aga-proxy. El elemento 5, añadido el 2026-09-25, concierne a los verificadores y se reprodujo el 2026-09-25
en las versiones actuales. El elemento 6, también añadido el 2026-09-25, concierne a aga-proxy con un upstream HTTP y se
reprodujo el 2026-09-25 en 3.6.2. El elemento 7, también añadido el 2026-09-25, concierne a los mensajes tools/call que aga-proxy rechaza
sin un recibo y se reprodujo el 2026-09-25 en 3.6.2 (su caso de mensaje sobredimensionado se añadió y reprodujo el
2026-09-26). Los elementos 8 a 12, añadidos el 2026-09-26, conciernen a texto no ASCII,
el costo de exportar evidencia, qué comprueban las restricciones de política, resultados de herramientas sobredimensionados y el canal de control; cada
uno se reprodujo el 2026-09-26 en 3.6.2, al igual que los casos de memoria y puerto de Windows añadidos al elemento 1 ese día. La misma
lista se mantiene en https://attestedintelligence.com/security.
- El puerto del agente escucha en todas las interfaces de red, sin autenticación. Cualquiera que pueda alcanzar el host en ese puerto puede enviar llamadas gobernadas a través del proxy. El proxy tampoco establece límite en el número de conexiones, por lo que aunque el mensaje sin terminar de cada conexión está limitado (elemento 7), la memoria que ocupan juntas no lo está: en 3.6.2, diez conexiones que cada una envió 7.5 MiB sin terminar un mensaje elevaron el conjunto de trabajo del proxy de 68 MiB a 392 MiB mientras permanecieron abiertas, y una llamada gobernada en otra conexión aún fue respondida. En Windows, un proceso que se ejecuta bajo la misma cuenta de usuario que el proxy puede vincular 127.0.0.1 en el mismo puerto mientras el proxy escucha, y un cliente local que se conecta a 127.0.0.1 entonces llega a ese proceso en lugar del proxy, sin verificación de política y sin recibo (medido en 3.6.2 con ambos procesos bajo una cuenta). Bloquee el tráfico entrante al puerto en el firewall del host, o admita solo al agente con política de red; en Windows, no ejecute nada no confiable bajo la cuenta del proxy, y verifique mientras el proxy se ejecuta que su proceso es el único que escucha en el puerto. El puerto de control está vinculado a loopback; consulte el elemento 12.
- Dos clientes que reutilizan un id JSON-RPC a través de un proxy pueden recibir los resultados de herramientas del otro. Solución alternativa, medida en 3.6.0: asigne a cada cliente su propio rango de ids, o ejecute un proxy por cliente. Con ids disjuntos, cada resultado llegó al cliente que lo solicitó.
- Cuando la clave de puerta de enlace se suministra a través de
AGA_GATEWAY_KEY(con o sin--ephemeral) oAGA_GATEWAY_KEY_FILE, el upstream stdio hereda esa variable (la semilla, o la ruta del archivo), por lo que el upstream se encuentra dentro del dominio de confianza de la clave. Solución alternativa, medida en 3.6.0: ejecute sin ninguna de las variables. El upstream entonces no ve ninguna, pero el proxy firma con una clave por proceso que no se puede fijar entre reinicios. - El modo
--upstream-urlreenvía JSON-RPC crudo sobre HTTP POST con solo un encabezado de tipo de contenido. No implementa el transporte MCP Streamable HTTP (el encabezado Accept, los encabezados de metadatos de solicitud y el manejo de flujo de eventos), por lo que un servidor HTTP MCP conforme a la especificación rechaza sus solicitudes. Solución alternativa: puente al servidor a través de stdio. - Un archivo de paquete puede repetir un nombre de campo en cualquier lugar: en un recibo, en el punto de control o en el sobre. Por ejemplo,
un
"decision": "PERMITTED"falsificado puede colocarse antes del"decision": "DENIED"firmado, o unleaf_countde punto de control falsificado antes del firmado. Los verificadores publicados (aga-verify 2.2.2, aga-governance 0.3.2, el verificador en este paquete, y los verificadores de referencia enaga-receipt-spec/verify/) y la página /verify del sitio leen la última ocurrencia, y cuando contiene el valor genuino informan VERIFIED, con procedencia cuando la clave está fijada. No rechazan el archivo, por lo que una herramienta o una persona que lea la primera ocurrencia puede ver un valor que nunca fue firmado. Medido en el paquete de muestra público, fijado a la clave de muestra: con el nombre repetido insertado en un recibo, en el punto de control o en el sobre, aga-verify 2.2.2, aga-governance 0.3.2, el verificador en este paquete y /verify informan VERIFIED, y un cambio real del valor del punto de control falla. Solución alternativa: trate la salida analizada del verificador como el contenido del registro, y rechace o marque archivos con nombres de campo repetidos antes de mostrarlos. Un rechazo estricto de nombres de campo repetidos está planificado para la versión revisada. - Un mensaje puede repetir el miembro
"method"cuando aga-proxy tiene un upstream HTTP (--upstream-url). Contools/callprimero y otro método al final, aga-proxy lee la última copia, por lo que nunca verifica la llamada de herramienta contra la política, y reenvía cada método que no seatools/callal upstream HTTP como los bytes exactos que recibió. Un upstream cuyo analizador JSON mantiene la primera copia de un nombre repetido entonces ejecuta la llamada de herramienta, incluso una que la política deniega. El paquete no contiene ningún recibo para esa llamada: nada en absoluto cuando el último método es uno que el proxy pasa sin recibo (comoping,initialize, un método de lista o una notificación), y de lo contrario solo un recibo de paso que nombra el último método. Un upstream que mantiene la última copia maneja el mensaje como el método que el proxy leyó. El upstream stdio, el predeterminado, no se ve afectado: el proxy re-serializa cada mensaje antes de escribirlo, por lo que el upstream recibe un método. Medido en 3.6.2 desde npm el 2026-09-25, con el perfil restrictivo y con el perfil permisivo predeterminado. Solución alternativa: mantenga el stdio predeterminado, o haga que el upstream HTTP rechace cualquier mensaje que repita un nombre de miembro. Un rechazo estricto de nombres de miembro repetidos en el proxy está planificado para la versión revisada. - aga-proxy no registra cada
tools/callque rechaza. Firma el recibo de untools/callantes de reenviar la llamada, por lo que con un upstream stdio una llamada que no puede registrar nunca llega a la herramienta (para un upstream HTTP, consulte el elemento 6), pero tal llamada no deja recibo. Estos casos se midieron en 3.6.2 desde npm el 2026-09-25, cada uno sin recibo y sin respuesta al cliente: untools/callcuyo nombre de herramienta es un número distinto de cero, un array o un objeto (un nombre de0,false,nullo una cadena vacía cuenta como sin nombre y obtiene un recibo DENIED y un error); uno cuyo nombre de herramienta o id de cadena contiene un sustituto no emparejado (el escape JSON\ud800, por ejemplo); bajo un archivo--policyen modoallowlistodenylistcuyo miembroconstraintsfalta o es null, cadatools/callcon un nombre de herramienta y argumentos que el proxy puede canonicalizar; y, bajo un archivo de lista de permitidos, una llamada que de otro modo permitiría y que lleva una ruta de cadena cuando elpath_prefixde esa herramienta no es ni una cadena ni false, 0 o null. El proxy se inicia con tal archivo de política, y reporta cada rechazo listado anteriormente solo en su propio stderr. Un mensaje enviado como un array de lote JSON-RPC o sin"jsonrpc": "2.0"se rechaza de manera diferente: el cliente recibe un error, y no hay recibo. Un mensaje de 8,388,608 caracteres o más (unidades de código UTF-16, alrededor de 8.4 millones), sin contar la nueva línea que lo termina pero contando un retorno de carro antes de esa nueva línea, también recibe un error y sin recibo, y el proxy entonces cierra la conexión, descartando cualquier respuesta aún pendiente en ella. El límite cuenta la entrada aún no dividida en mensajes, por lo que un mensaje justo por debajo del límite puede ser rechazado de la misma manera cuando la lectura que lo completa también lleva suficiente entrada después de él para pasar el límite; si eso sucede depende de dónde caen las lecturas. En 3.6.2, cuando un mensaje de 100 caracteres, un mensaje 58 caracteres por debajo del límite y un mensaje de 100,000 caracteres se enviaron en una sola escritura, el primero fue respondido, el segundo recibió el error y la conexión se cerró; enviados sin el mensaje de 100,000 caracteres, o sin el de 100 caracteres, cada mensaje fue reenviado. Estos son los casos medidos, no una prueba de que ninguna otra entrada haga lo mismo. Solución alternativa: dé a cada archivo de política un objetoconstraintscuyos valorespath_prefixsean cadenas, y haga que el cliente agote el tiempo de espera de una llamada que no recibe respuesta. Un recibo DENIED y un error para un nombre de herramienta malformado, y una verificación del archivo de política al inicio, están planificados para la versión revisada. - aga-proxy puede alterar texto no ASCII cuyos bytes se dividen entre dos lecturas. Decodifica cada fragmento que lee de
la conexión del agente, y de la salida de un upstream stdio, por su cuenta, por lo que un carácter dividido entre dos fragmentos
se convierte en uno o más caracteres de reemplazo (U+FFFD). Los argumentos de una llamada de herramienta pueden entonces llegar al upstream alterados, y
el hash de argumentos del recibo es el hash de los argumentos alterados; un resultado no ASCII grande de un upstream stdio puede
llegar al agente alterado. El resultado de un upstream HTTP se decodifica completo. Si ocurre una división depende de cómo llegan los bytes,
por lo que cualquier mensaje con texto no ASCII puede verse afectado, y los grandes más a menudo. Medido en 3.6.2 desde npm el
2026-09-26: una división forzada dentro de "é" llegó al upstream como dos caracteres de reemplazo, y un resultado de 200,000 "€"
llegó al cliente con 15 caracteres de reemplazo en él. Solución alternativa: envíe JSON cuyos caracteres no ASCII estén escritos
como escapes
\uXXXX, para que cada byte que el proxy lee del agente sea ASCII, y haga que un upstream stdio haga lo mismo; una división forzada del mensaje escapado entonces llegó intacto. Una corrección está planificada para la versión revisada. - Exportar el paquete de evidencia toma tiempo que crece con el cuadrado del número de recibos, y aga-proxy
no maneja nada más mientras se ejecuta: cada llamada gobernada espera hasta que la exportación termina. Una llamada reenviada a un upstream stdio
que no ha respondido cuando comienza una exportación recibe un error de tiempo de espera si la exportación termina más de 30 segundos
después de que la llamada fue reenviada, aunque el upstream la ejecutó y su recibo dice PERMITTED, por lo que un agente que reintenta
puede ejecutar la herramienta dos veces. Medido en 3.6.2 desde npm el
2026-09-26 a través del
GET /exportdel canal de control: 2.8 segundos a 1,000 recibos y 17.4 segundos a 2,500, con untools/callenviado durante la exportación esperando tanto; a 4,000 recibos una exportación tomó 43.8 segundos, y una llamada reenviada justo antes, que el upstream respondió en 2 segundos, recibió el error de tiempo de espera. A 1,000 a 4,000 recibos un paquete compacto tomó alrededor de 1.7 a 1.9 KB por recibo, aumentando con el conteo. Una auditoría el mismo día midió 88 a 113 segundos a 5,000 recibos. El tiempo de verificación crece casi linealmente. Solución alternativa: cada exportación cubre cada recibo desde que el proxy se inició y no acorta la cadena, por lo que limite la cadena reiniciando el proxy en un horario: pause los agentes, exporte y verifique, luego reinicie. Un reinicio comienza una nueva cadena que no está vinculada a la última y restablece los conteos de límite de velocidad; con una clave por proceso (--ephemeral, o niAGA_GATEWAY_KEYniAGA_GATEWAY_KEY_FILEestablecidos) también comienza una nueva clave de firma, impresa al inicio, que no se puede fijar entre reinicios (elemento 3). Exporte fuera de períodos ocupados, y exporte y verifique antes de cualquier detención, porque la cadena en vivo se mantiene en memoria y una detención pierde recibos no exportados aún. Una corrección que deja los bytes del paquete sin cambios está planificada para la versión revisada. - Las restricciones de política verifican menos de lo que sus nombres sugieren. Un
path_prefixse verifica solo cuando el valor bajo la clave verificada (path, o las claves que una regla lista enpath_keys) es una cadena, por lo que la misma ruta enviada dentro de un array o un objeto no se verifica.denied_patternscoinciden con distinción de mayúsculas y minúsculas y solo en argumentos de cadena de nivel superior, por lo que un comando en mayúsculas, o uno dentro de un array o un objeto anidado, no coincide. Una clave de restricción que el proxy no reconoce, como un error ortográfico, se ignora sin advertencia, y un valor del tipo JSON incorrecto no se rechaza:allowed: "false", una cadena, permite la herramienta; en modo de lista de denegados una herramienta listada comofalse,nullo0en lugar de un objeto se permite; y una cadenapath_keysno vacía en lugar de un array hace que la verificación lea cada carácter como un nombre de clave, por lo que la clave prevista queda sin verificar. Los límites de velocidad cuentan por nombre de herramienta en todo el proxy, compartidos por cada cliente, y en modo de lista de permitidos el límite se verifica antes de las reglas de ruta y patrón, por lo que una llamada que esas reglas deniegan aún usa un espacio. Medido en 3.6.2 desde npm el 2026-09-26 con archivos de política de lista de permitidos y denegados: unpath_prefixde/homedenegó"/etc/passwd"y reenvió["/etc/passwd"]; un patrón denegado derm -rfdenegórm -rf /y reenviadoRM -RF /y el mismo comando dentro de un arreglo; una regla escritadenied_patterndenegó nada;allowed: "false"reenvió la llamada en ambos modos; una entrada de lista de denegación defalsereenvió la llamada;path_keys: "path"reenvió/etc/passwdmás allá de un prefijo/home; y, bajo un límite de 2 por minuto, dos llamadas denegadas por un prefijo/homedejaron una tercera llamada, a una ruta bajo/home, denegada por el límite de tasa, mientras que después de una denegación de ese tipo esa llamada fue reenviada. Solución alternativa: trate las reglas de ruta y patrón como una conveniencia más que como un límite, restrinja las rutas en el servidor ascendente mismo, y verifique las claves de un archivo de políticas contra los nombres de restricción endist/proxy/types.d.ts. Se planean verificaciones que fallan de forma cerrada en estas entradas, y una verificación del archivo de políticas al inicio, para la versión revisada. - Una respuesta de un upstream stdio cuya línea JSON tiene 8,388,608 caracteres o más (unidades de código UTF-16, contando el escape JSON y un retorno de carro antes del salto de línea, pero no el salto de línea en sí) se descarta. La llamada ya tiene un recibo PERMITIDO, y el agente recibe un error de tiempo de espera después de 30 segundos, por lo que un agente que reintenta puede ejecutar la herramienta dos veces; el proxy informa el descarte solo en su propia salida de error estándar. El límite cuenta la salida del upstream aún no dividida en líneas, por lo que una respuesta justo por debajo del límite puede descartarse cuando la lectura que la completa también lleva suficiente salida después de ella para superar el límite; cada respuesta posterior que comienza en esa lectura, posiblemente a llamadas de otros clientes, se descarta con ella. Si eso sucede depende de dónde caen las lecturas. Medido en 3.6.2 desde npm el 2026-09-26: un resultado de 9,000,000 caracteres fue descartado y el agente recibió el tiempo de espera después de 30.0 segundos, mientras que un resultado de 1,000,000 caracteres regresó en 31 milisegundos. A través de un proxy en ejecución, una línea de respuesta de 8,388,607 caracteres fue devuelta y una de 8,388,608 fue descartada; y cuando el upstream respondió tres llamadas en una sola escritura (100 caracteres y 58 bajo el límite para un cliente, luego 100 para el otro), la primera fue respondida y las otras dos, una de ellas la del otro cliente, agotaron el tiempo de espera, mientras que las mismas respuestas sin la respuesta principal de 100 caracteres fueron ambas devueltas. Estos son los casos medidos. Una respuesta de un upstream HTTP se lee completa y no se descarta de esta manera; en Linux, una en el mismo límite cierra la conexión del agente en su lugar (elemento 13). Solución alternativa: mantenga los resultados de las herramientas muy por debajo del límite, por ejemplo leyendo archivos grandes en partes, y donde los resultados sean grandes ejecute un proxy por cliente. Se planea un error devuelto de inmediato para la versión revisada.
- El canal de control no verifica el encabezado Host u Origin de una solicitud. Escucha en 127.0.0.1 (puerto 18801 por
defecto) para que un
aga-proxy exportseparado pueda obtener el paquete en vivo (rutas/export,/statusy/receipts). Medido en 3.6.2 desde npm el 2026-09-26:GET /receiptsyGET /exportenviados con el Host y Origin de otro sitio devolvieron 200, y ambos llevaban la ruta del argumento de una llamada denegada en su razón de denegación. Una página web abierta en un navegador en el mismo host puede, por lo tanto, leer los recibos en vivo y el paquete de evidencia a través del rebinding de DNS, a menos que el navegador bloquee las solicitudes de un sitio público a la dirección de bucle local; cualquier usuario local en el host también puede leerlos. Una página también puede iniciar una exportación con unGET /exportsimple sin rebinding, a menos que el navegador lo bloquee, y cada exportación retiene las llamadas gobernadas mientras se ejecuta (elemento 9). La CLI no tiene una opción destinada a apagar el canal; un--control-portde 70000, o cualquier número por encima de 65535, lo deja sin iniciar mientras la gobernanza se ejecuta, pero entonces ningún comando puede exportar los recibos del proxy en ejecución. Solución alternativa: no navegue por la web en el host mientras el proxy se ejecuta, o ejecute el proxy en un host donde nadie lo haga, y en un host compartido con otros usuarios trate los recibos en vivo como legibles por todos ellos. Se planea una verificación de Host y Origin para la versión revisada. - En Linux, una respuesta de un upstream HTTP (
--upstream-url) cuya línea JSON, tal como el proxy la serializa, tiene 8,388,608 caracteres o más (unidades de código UTF-16, contando el escape JSON pero no el salto de línea) cierra la conexión del agente. El proxy escribe toda la línea al socket del agente en una sola llamada. Un kernel de Linux con sus buffers de socket predeterminados toma solo parte de una escritura de ese tamaño; el resto sale a medida que el cliente lee, pero toda la línea cuenta como en espera hasta que haya salido por completo, por lo que la protección del proxy contra un cliente que no lee sus respuestas ve más de 8,388,608 caracteres en espera, incluido el salto de línea, y destruye el socket. La llamada ya tiene un recibo PERMITIDO y el upstream ha ejecutado la herramienta; la conexión del agente se cierra a mitad de la respuesta sin mensaje de error, por lo que un agente que se reconecta y reintenta puede ejecutar la herramienta dos veces; cada otra llamada en vuelo en esa conexión se pierde con ella; y el proxy no informa nada. Medido en 3.6.2 desde npm el 2026-09-26 en un host Linux 6.18 con Node 24 y los buffers de socket predeterminados (net.ipv4.tcp_wmem4096 16384 4194304): líneas de resultado de 4,000,000, 8,000,000, 8,388,606 y 8,388,607 caracteres fueron devueltas, y líneas de 8,388,608, 8,388,609, 9,000,000, 10,000,000, 12,000,000, 16,000,000, 20,000,000 y 32,000,000 caracteres cerraron la conexión después de 3.1 a 5.0 MB de la respuesta habían llegado; un cliente que no leyó nada durante 4 segundos recibió un resultado de 4,000,000 caracteres y perdió uno de 9,000,000 caracteres después de 2.7 MB. En Windows 11 el mismo proxy devolvió un resultado de 20,000,000 caracteres, y uno de 9,000,000 caracteres a un cliente que no leyó nada durante 4 segundos, porque ese kernel tomó cada escritura completa. Una respuesta de un upstream stdio de este tamaño se descarta en su lugar (elemento 11). Solución alternativa: mantenga los resultados de las herramientas muy por debajo del límite, por ejemplo leyendo archivos grandes en partes. Se planea un error devuelto de inmediato para la versión revisada. No se nombra una versión fija hasta que se publique una.
Seguridad
Consulta SECURITY.md para informar sobre vulnerabilidades.
Contribuciones
Consulta CONTRIBUTING.md para la configuración de desarrollo y las pautas.
Licencia
MIT. El directorio aga-receipt-spec/ tiene su propia
licencia Apache-2.0 (consulta aga-receipt-spec/LICENSE).
Attested Intelligence Holdings LLC