Agentic Wallet Guardian

Motor de decisión autoalojado que se sitúa entre los agentes de IA y la ejecución en blockchain, devolviendo ALLOW/WARN/BLOCK antes de que se firme cualquier transacción.

Documentación

Agentic Wallet Guardian

agentic-wallet-guardian-v3 MCP server

📄 Leer el white paper

Permite que los agentes de IA realicen transacciones on-chain sin darles control ilimitado sobre la wallet. Guardian evalúa cada acción propuesta antes de firmar o transmitir, y devuelve una decisión explicable de PERMITIR / ADVERTIR / BLOQUEAR.

POST /decision   ->   ALLOW / WARN / BLOCK  (with a reasoned explanation)

Se ejecuta en tu propia infraestructura, usando tus propias reglas de política y tus propios datos de reputación; consulta Por qué autoalojado para entender por qué esto importa y en qué se diferencia de llamar directamente a una API de seguridad alojada.

Guardian es agnóstico respecto a cadenas y casos de uso: Arc/USDC a continuación es una implementación en vivo, no el alcance completo. Consulta docs/hackathons.md para ver a qué pista se dirige esta presentación y por qué.

Demo en Arc Mainnet

Demo en vivo: http://77.239.125.37:8765/arc

Video de demostración: https://youtu.be/srH0ZLwtwqQ

Agentic Wallet Guardian está implementado en Arc mainnet e incluye una demo de navegador en vivo para pagos con USDC. Guardian evalúa la operación solicitada antes de la ejecución, aplica sus políticas de seguridad, y solo una operación aprobada se pasa a la wallet del usuario para firmar.

Transacción verificada en Arc mainnet: 0xd781e8b04b5ca89c3a34fcec50a6636049f7647d2b0e1b2bb64d5b1ee54daadf

La transacción se ejecutó exitosamente en Arc mainnet usando USDC a través de la demo de Guardian.


Véalo decidir en vivo: ejecute la API localmente (GUARDIAN_ENABLE_CORS_FOR_BROWSER_DEMO=true uvicorn api.main:app --reload), then open examples/browser-demo.html en un navegador: sin paso de compilación, sin servidor para la página en sí. Cada botón de escenario envía un POST /decision real a tu instancia en ejecución y renderiza la respuesta real (puntuación de riesgo, cada señal que la alimentó, cada regla de política que se activó): nada en la página está guionizado o falsificado. GUARDIAN_ENABLE_CORS_FOR_BROWSER_DEMO está desactivado por defecto (consulta guardian/config.py) ya que es específicamente para este caso de demo local, no algo que deba dejarse activado para una implementación real.


Por qué autoalojado

Existen buenas alternativas alojadas para la seguridad de transacciones de agentes (AgentGuard de GoPlus, Blockaid, Chainalysis/TRM para cumplimiento). Si solo quieres una puntuación de riesgo y no te importa quién ve la consulta, llamar a una de esas directamente es menos trabajo que ejecutar esto. Guardian existe para los casos donde ese intercambio no funciona para ti:

  • Nada sobre qué wallets, contratos o montos tocan tus agentes sale de tu infraestructura. Las verificaciones de inteligencia de amenazas y de permitir/denegar contratos son archivos JSON locales que tú mismo completas (consulta data/threat_lists/README.md), no una llamada de consulta a un tercero. Una API alojada inherentemente ve cada dirección y monto que le preguntas.
  • Tus reglas de política viven en tu código, no en un panel de control de un proveedor. Límites de gasto, puertas de reputación y qué tipos de acción requieren confirmación son Python simple en guardian/policy/, revisables y modificables sin esperar la hoja de ruta de producto de nadie más.
  • Sin tarifas por llamada ni límites de tasa impuestos por otros — solo los que configures para tus propios usuarios (GUARDIAN_RATE_LIMIT_PER_MINUTE).
  • Sin bloqueo de proveedor. Cada fuente de datos externa (endpoint RPC, instancia de Blockscout, DexScreener) es intercambiable detrás de una interfaz de proveedor pequeña; consulta Arquitectura.

El intercambio honesto en la otra dirección: también asumes la responsabilidad de ejecutarlo, mantener tus listas locales de amenazas actualizadas, y no obtienes la cobertura de cadenas de un proveedor alojado ni un equipo dedicado de investigación de amenazas gratis. Esta es la elección correcta para equipos que necesitan específicamente soberanía de datos o personalización profunda de políticas, no una mejora estricta sobre cada opción alojada.


Arquitectura

                AI Agent
                    |
                    v
             Action Intent
   { agent_id, wallet, chain, action_type,
     target, amount, metadata }
                    |
                    v
        ┌───────────────────────────────┐
        │   Guardian Decision Engine    │
        ├───────────────────────────────┤
        │  1. Hard Rules                │  <- chain support, sanity checks
        │  2. Wallet Intelligence       │  <- mock | real RPC (web3.py)
        │  3. Token Intelligence        │  <- mock | real DexScreener | real GoPlus
        │  4. Contract Intelligence     │  <- local lists, then mock | real Blockscout | real GoPlus
        │  5. Simulation                │  <- mock | real eth_call dry-run (see below)
        │  6. Threat Intelligence       │  <- local JSON allow/deny lists
        │  7. Anomaly Detection         │  <- vs. this agent's own history (see below)
        │  8. Policy Engine             │  <- spending caps, reputation gates
        │  9. Risk Fusion               │  <- signals -> single 0-100 score
        │ 10. Reputation Adjustment     │
        │ 11. Explanation               │  <- evidence -> human-readable reasons
        └───────────────────────────────┘
                    |
                    v
          ALLOW / WARN / BLOCK
                    |
                    v
          Blockchain Execution

Cada fuente de datos en los pasos 2-4 es una interfaz de proveedor pequeña con una implementación simulada (cero configuración, cero llamadas de red) y una real, seleccionada por fuente mediante variable de entorno; consulta .env.example. Cambiar de modo demo a una implementación real es un cambio de configuración, no un cambio de código.

Estructura del repositorio

guardian/
    config.py          GuardianConfig - the one place that reads os.environ
    core/               ActionIntent, Signal, Decision, EvaluationContext
                            (zero external dependencies - no pydantic/FastAPI)
    decision/           DecisionEngine (orchestrator), RiskFusionEngine, hard rules
    reasoning/          explanation + confidence builders
    intelligence/
        wallet/           analyzer.py + providers.py (mock | RpcWalletDataProvider)
        token/            analyzer.py + providers.py (mock | DexScreenerTokenDataProvider | GoPlusTokenDataProvider)
        contract/         analyzer.py + providers.py (mock | BlockscoutContractDataProvider | GoPlusContractDataProvider)
        simulation/       pre-execution dry-run (mock | real eth_call) + tx_builder.py (real calldata for transfer/approve)
        goplus_client.py  shared GoPlus Token Security API client (used by both contract + token)
        threat/           blocklist.py (local AddressList) + intelligence.py
    policy/             PolicyEngine + policy templates (spending caps, reputation gates)
    reputation/         AgentReputation (score derived from decision history)
    memory/             storage.py (protocol) + InMemoryStorage + sqlite_storage.py
api/
    main.py             FastAPI app: /decision, /health, /capabilities, /agents/{id}/history, /demo/{scenario}
    security.py         API-key auth dependency + rate-limit middleware
    schemas.py          pydantic request/response models (API boundary only)
mcp_server.py           MCP stdio server - same DecisionEngine, no HTTP required
data/threat_lists/      local, operator-maintained allow/deny lists (empty by default - see its README)
scripts/
    refresh_ofac_list.py   fetch OFAC's public SDN list into the local threat list
tests/                  101 tests covering the engine, policy, reputation, and every provider

guardian/* es intencionalmente libre de dependencias (solo biblioteca estándar, excepto donde un proveedor real necesita httpx o web3), para que el núcleo de decisión pueda probarse unitariamente, incrustarse en otro servicio o portarse a un framework web diferente sin arrastrar FastAPI. Solo api/ toca pydantic/FastAPI.


Honestidad sobre el estado actual

Esto es infraestructura de decisión real, ejecutable y probada, con fuentes de datos reales (no simuladas) disponibles para cada fuente de señal; pero "disponible" no es lo mismo que "cambia un interruptor y confía ciegamente". Detalles:

  • Wallet (proveedor RPC): is_contract y tx_count (basado en nonce) son confiables con cualquier endpoint JSON-RPC. La antigüedad de la wallet requiere un nodo con capacidad de archivo y está desactivada por defecto (GUARDIAN_RPC_ESTIMATE_AGE=false): la mayoría de los endpoints RPC públicos gratuitos no sirven estado histórico, por lo que esto falla cerrado a "desconocido" en lugar de adivinar.
  • Contrato (proveedor Blockscout): consultas reales de estado de verificación contra una instancia pública de Blockscout. Su esquema de respuesta exacto y los límites de tasa pueden cambiar; esto está escrito para degradar a "desconocido" ante cualquier respuesta inesperada, nunca para fabricar una respuesta, pero no ha sido probado bajo carga contra tráfico de producción.
  • Token (proveedor DexScreener): datos reales de liquidez, pero hacer coincidir un símbolo de ticker simple con un par on-chain es inherentemente ambiguo (muchos tokens no relacionados comparten un símbolo, y los estafadores acuñan deliberadamente imitaciones). El proveedor elige el par de mayor liquidez en la cadena solicitada e informa su propia confianza de coincidencia en lugar de presentar una suposición como cierta; para cualquier caso donde esa ambigüedad importe, haz coincidir por dirección de contrato en lugar de símbolo.
  • Contrato + Token (proveedor GoPlus): seguridad real de contrato (el propietario puede drenar, acuñable, autodestrucción, propietario oculto) y seguridad de trading (honeypot, impuesto de compra/venta, lista negra, transferencias pausables, concentración de tenedores) desde la API de Seguridad de Tokens de GoPlus, lo que significa significativamente más tipos de señal de los que Blockscout/DexScreener dan individualmente, ya que el análisis estático propio de GoPlus cubre ambos en una sola llamada. Dos límites reales: solo tiene datos para contratos que realmente ha analizado (principalmente contratos de tokens, no contratos genéricos de dApp/router), y GoPlusTokenDataProvider necesita una dirección de contrato; un símbolo simple como "PEPE" no puede resolverse y se informa honestamente como no verificable en lugar de adivinarse.
  • La lista de direcciones sancionadas es real, con datos poblados: 103 direcciones (100 EVM + 3 Solana) de la lista SDN de OFAC, vía 0xB10C/ofac-sanctioned-digital-currency-addresses: verificada de extremo a extremo (una dirección sancionada conocida activa correctamente BLOCK a través del pipeline completo) y verificada para reflejar correctamente eliminaciones, no solo adiciones (las direcciones de Tornado Cash, eliminadas de la lista SDN en marzo de 2025, están correctamente ausentes). Vuelve a ejecutar scripts/refresh_ofac_list.py periódicamente: las sanciones cambian en ambas direcciones.
  • malicious_contracts.json / verified_contracts.json aún se envían vacías a propósito (consulta data/threat_lists/README.md): no hay una única fuente autoritativa para "contrato malicioso" como la lista de OFAC es autoritativa para sanciones, por lo que poblar estas es una decisión de criterio para quien opera esta instancia, no algo para sembrar por defecto con entradas no verificadas.
  • La simulación es real, pero condicional. RpcSimulationProvider (GUARDIAN_SIMULATION_PROVIDER=rpc) realmente hace una prueba en seco de una transacción vía eth_call/eth_estimateGas contra el estado actual de la cadena: un revert regresa con su razón real, no una suposición, y los montos de ERC-20 approve() se decodifican de calldata real en lugar de inferirse. Esto se activa cuando el llamador proporciona calldata sin procesar vía intent.metadata["data"], O — nuevo — cuando GUARDIAN_TX_BUILDER=rpc también está configurado y la intención es un transfer o approve simple (consulta el siguiente punto). Una intención swap sin transacción construida aún no tiene nada para probar en seco: Guardian informa eso honestamente (simulation_not_attempted) en lugar de adivinar.
  • La construcción de transacciones cierra parte de esa brecha, deliberadamente no toda. RpcTransactionBuilder (GUARDIAN_TX_BUILDER=rpc) convierte una intención semántica transfer/approve en calldata real: obtiene el decimals() real del token vía RPC en lugar de asumir 18 (una suposición incorrecta allí escalaría el monto por órdenes de magnitud), y deliberadamente no tiene un registro de direcciones de tokens codificado: un símbolo simple como "USDC" se rechaza en lugar de adivinarse, ya que una dirección incorrecta aquí no sería solo una mala señal de riesgo, sería un artefacto que podría terminar en una transacción real. swap está construido solo contra Uniswap V2 Router02 (un contrato inmutable y bien conocido; los selectores de funciones se calculan localmente vía Web3.keccak, no copiados de memoria): cotización real on-chain de getAmountsOut(), max_slippage_bps proporcionado por el llamador requerido (nunca un valor predeterminado, mismo razonamiento que los decimales anteriores). bridge es un problema genuinamente abierto de enrutamiento L2/puente en general: docenas de protocolos, modelos de confianza muy diferentes; pero este módulo maneja una porción bien delimitada: depósitos L1 -> L2 a través del puente oficial OP Stack de la cadena de destino (actualmente: Base y Optimism: depositETHTo/depositERC20To en L1StandardBridge, ambas direcciones verificadas de forma cruzada de manera independiente — Base contra la etiqueta de Etherscan más basehub.org, Optimism contra el registro oficial ethereum-optimism/superchain-registry más una segunda configuración independiente de herramientas de desarrollo — antes de codificarse). Los retiros L2 -> L1 NO se construyen: ese es un flujo genuinamente diferente, mucho más lento, de prueba/ventana de desafío, no una variante de la llamada de depósito. Puentear a cualquier otro lugar, o vía cualquier puente no canónico, devuelve None en lugar de adivinar.
  • La verificación de intención ahora puede realmente hacer cumplir, no solo marcar. decision/intent_verification.py compara el monto approve declarado por un agente contra lo que el calldata simulado realmente codifica, pero esa comparación necesita el decimals() del token para convertir entre unidades humanas y atómicas. GUARDIAN_DECIMALS_PROVIDER=rpc (RpcTokenDecimalsProvider, consulta guardian/intelligence/token/decimals.py) obtiene eso de verdad vía eth_call, almacenado en caché para siempre por (cadena, token) ya que el decimals() de un contrato implementado no puede cambiar. Dejado en su valor predeterminado null, un desajuste que este módulo podría detectar de otro modo degrada a un honesto WARN de "no se puede verificar" — la misma regla de "sin suposiciones silenciosas" que en todas partes de este módulo, no una brecha que se pasó por alto. RpcTransactionBuilder comparte esta misma caché cuando ambos están configurados con un proveedor real, en lugar de hacer su propia consulta independiente y sin caché para el mismo token.
  • Almacenamiento: InMemoryStorage (predeterminado, cero configuración), SQLiteStorage (GUARDIAN_STORAGE_BACKEND=sqlite — persiste entre reinicios, sin infraestructura externa), o PostgresStorage (GUARDIAN_STORAGE_BACKEND=postgres + GUARDIAN_POSTGRES_DSN — la opción adecuada para múltiples réplicas detrás de un balanceador de carga, donde el modelo de escritor único de SQLite se convierte en el cuello de botella; pip install -r requirements-postgres.txt). Probado contra una instancia real local de Postgres, no simulado; consulta tests/test_postgres_storage.py. Redis sigue abierto si lo quieres específicamente; la interfaz de dos métodos MemoryBackend es lo suficientemente pequeña para implementarse contra cualquier cosa.
  • Autenticación/límites de tasa de API son intencionalmente mínimos — construidos para una instancia autoalojada detrás de tu propio límite de red, no un gateway multiinquilino. Pon un gateway de API real al frente si necesitas eso.
  • No auditado en seguridad. El motor de políticas y la lógica de fusión de riesgos no han sido revisados por nadie fuera de este repositorio. Trata BLOCK como una señal fuerte, no una garantía, hasta que eso suceda.

Todo lo que está aguas abajo de un Signal — fusión, políticas, reputación, explicación, la API — no necesita cambiar a medida que cualquiera de lo anterior se endurezca más. Ese límite es el contrato de diseño real aquí.


Inicio rápido

Zero-config demo mode (mock providers, in-memory storage, no auth):

pip install -r requirements.txt
uvicorn api.main:app --reload

Or with Docker:

docker compose up --build

Try the canned scenarios:

curl http://localhost:8000/demo/safe
curl http://localhost:8000/demo/unknown
curl http://localhost:8000/demo/malicious

Or submit your own intent:

curl -X POST http://localhost:8000/decision \
  -H "Content-Type: application/json" \
  -d '{
        "agent_id": "trading-agent-001",
        "wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
        "chain": "ethereum",
        "action_type": "swap",
        "from_token": "ETH",
        "to_token": "USDC",
        "amount": 5
      }'

Going from demo to a real self-hosted deployment

Copy .env.example to .env and adjust:

cp .env.example .env

At minimum for a real deployment: set GUARDIAN_API_KEY (auth is off by default), GUARDIAN_STORAGE_BACKEND=sqlite (persistence), and whichever GUARDIAN_*_PROVIDER variables you want pointed at real data instead of mock - see the comments in .env.example for every option, and RpcWalletDataProvider/BlockscoutContractDataProvider/ DexScreenerTokenDataProvider/GoPlusContractDataProvider/ GoPlusTokenDataProvider's docstrings for what each one actually gives you.

If more than one agent shares this deployment, also set GUARDIAN_AGENT_API_KEYS (format: agent_id:key,agent_id2:key2). A single GUARDIAN_API_KEY only proves a caller holds a valid key - it does not prove which agent_id a given request actually came from, since agent_id is just a field in the request body. Anyone holding the shared key can submit any agent_id and inherit that agent_id's accumulated reputation and capability grants. GUARDIAN_AGENT_API_KEYS binds each agent_id to its own key; GUARDIAN_API_KEY, if also set, keeps working as a master key that can act as any agent, for admin/testing use. For a genuinely single-agent deployment, GUARDIAN_API_KEY alone is fine.

MCP (no HTTP required)

For agent frameworks that speak MCP (LangChain, CrewAI, Claude Desktop, etc.), mcp_server.py exposes the same decision engine as two tools (evaluate_action, get_agent_history) over stdio - install requirements-mcp.txt alongside requirements.txt (they resolve into one environment; see the comment at the top of requirements-mcp.txt) and point your MCP client at python mcp_server.py.


Arc mainnet payment demo

Guardian 3.2 adds a small, non-custodial Arc mainnet surface for autonomous USDC payments.

  • Arc mainnet, chain ID 5042, official RPC https://rpc.mainnet.arc.io
  • Arc USDC ERC-20 interface 0x3600000000000000000000000000000000000000 (6 decimals)
  • Guardian runs the normal hard-rules, intelligence, simulation, policy and risk pipeline before it releases a transaction
  • the demo policy caps autonomous payments at 5 USDC and blocks approve/swap/bridge/contract-call actions on this surface
  • only an ALLOW decision produces a signable transaction; the browser wallet remains the only signer
  • the public demo keeps one bounded history identity (arc-demo-agent) so visitor traffic cannot create unbounded per-agent memory keys
  • open /arc on a running instance to connect a wallet, ask Guardian, and sign the resulting Arc payment

Manual Arc verification:

python scripts/verify_arc_mainnet.py

The script checks chain ID, live block height, gas price and the mainnet USDC decimals() call. It does not require a private key.

Running the tests

pip install -r requirements.txt -r requirements-chain.txt -r requirements-mcp.txt
pytest -q

requirements-chain.txt (web3) is needed by the RPC and on-chain attestation tests. requirements-mcp.txt installs the MCP SDK used by mcp_server.py. PyJWT and cryptography are core dependencies because OAA attestations use JWTs and Ed25519 signing. The CI install matches this full test environment.

PYTHONPATH=. python3 -m unittest discover -s tests -v

CI (.github/workflows/ci.yml) runs the full suite on every push/PR against Python 3.11 and 3.12.


Signed, verifiable decisions (OAA)

Every decision this service returns — from a single policy check up through the full pipeline — is signed as an OAA (Open Agent Attestation) token: an Ed25519-signed JWT wrapping the decision, the action, and the reason.

Anyone holding the public key can verify a decision offline, without calling back to whatever instance of Guardian issued it — useful for an auditor, a downstream service, or just a record you want to trust later without trusting the server that produced it.

python examples/example_oaa_attestation.py
python examples/example_full_pipeline.py   # capability -> intent -> engine -> OAA

The reference OAA implementation is ~150 lines (oaa.py/attestation.py upstream) and is shared, unmodified, across this project and agent-guardrail — same signing format, same verification path, no per-project fork.


Using Guardian in front of MetaMask Agent Wallet

MetaMask Agent Wallet's Guard Mode / Beast Mode apply the same static spend limits and allowlists to every agent. Guardian is a second, independent check in front of it: does this specific action look right for this agent, right now — before the mm CLI is ever invoked.

skills/guardian-check/ is a standard Agent Skill — the same open format MetaMask itself uses for mm (npx skills add MetaMask/agent-skills). Install it alongside MetaMask's own skill in any Agent-Skills-compatible runtime (Claude Code, Cursor, Codex, OpenClaw), and the agent will call a running Guardian instance for an ALLOW/WARN/BLOCK decision before running any mm command that moves funds — mm send, mm swap, mm bridge, mm perps, mm predict trade, mm earn, mm aave, mm pay.

Guardian never holds keys and never executes anything — mm remains the only thing that signs or broadcasts. This is a decision gate the agent is instructed to consult first, not a modification to MetaMask's own pipeline (there's no public hook for that today).

uvicorn api.main:app --reload   # run Guardian locally
export GUARDIAN_API_URL="http://localhost:8000"
python skills/guardian-check/scripts/check.py \
  --agent-id my-agent --wallet 0x... --chain ethereum \
  --action-type transfer --target 0x... --amount 50

From advisory to enforced: GuardianValidator

Everything above is advisory - Guardian tells you ALLOW/WARN/BLOCK, but the caller still has to choose to respect that. onchain/ is a real ERC-7579 validator module for ERC-4337 smart accounts that closes that gap: once installed, the account's UserOperations only ever reach the chain if a trusted Guardian signer attested, for that exact operation, that the decision was ALLOW - not something an agent can skip asking or ignore the answer to. See onchain/README.md for why it needs a second, EVM-native signature format alongside OAA (Ed25519 has no EVM precompile and costs ~2,000,000 gas to verify in pure Solidity; this module's entire validateUserOp costs 27k-59k gas), what's deliberately out of scope (WARN never passes on-chain; no professional audit yet), and how to build, test, and deploy it - including a test that verifies a signature produced by real, running Python (guardian/onchain_attestation.py) is accepted by the real Solidity contract, not two implementations that only agree with themselves.


Roadmap

  1. Reemplazar los analizadores simulados de wallet/token/contrato con fuentes de datos reales. Hecho - ver Honestidad sobre el estado actual para lo que "real" cubre y no cubre aún por fuente.
  2. Conectar la simulación real previa a la ejecución. Hecho para transfer/approve de extremo a extremo (GUARDIAN_SIMULATION_PROVIDER=rpc + GUARDIAN_TX_BUILDER=rpc - ver Honestidad sobre el estado actual). swap necesita enrutamiento DEX real. Hecho contra Uniswap V2 Router02 - cotización real en cadena de getAmountsOut(), max_slippage_bps explícito proporcionado por el llamador (nunca por defecto), sin calldata construido sin una cotización real. Se corrigió un error real encontrado al construir esto: la simulación se ejecutaba en seco contra intent.target (el destinatario/gastador codificado dentro del calldata ERC-20) en lugar del contrato real al que se llamaba (from_token) - lo que significa que la simulación de transfer/approve "tenía éxito" silenciosamente contra cualquier destinatario EOA, independientemente de si la llamada real habría revertido. BuiltTransaction ahora lleva un to explícito; ver tests/test_tx_builder.py para las pruebas de regresión que lo habrían detectado. bridge sigue abierto. Hecho para depósitos L1->L2 a Base y Optimism a través del L1StandardBridge oficial de OP Stack (depositETHTo/depositERC20To) - otros destinos, otros protocolos de puente y retiros L2->L1 siguen abiertos; ver Honestidad sobre el estado actual.
  3. Poblar los feeds de inteligencia de amenazas / sanciones; dejar de enviar conjuntos vacíos. Hecho para sanciones (sanctioned_addresses.json - 103 direcciones reales de OFAC SDN, actualizables mediante scripts/refresh_ofac_list.py). malicious_contracts.json / verified_contracts.json siguen vacíos por diseño - no existe una única fuente autoritativa para sembrarlos como lo hace la lista de OFAC para sanciones.
  4. Reemplazar InMemoryStorage por un backend persistente. SQLiteStorage está disponible; un backend Postgres/Redis sigue abierto para despliegues multi-réplica. PostgresStorage hecho - probado contra una instancia local real de Postgres (tests/test_postgres_storage.py), misma interfaz de dos métodos MemoryBackend que los otros backends. Redis sigue abierto si se desea específicamente.
  5. Añadir un wrapper de servidor MCP. Hecho (mcp_server.py). Un SDK empaquetado de Python/TypeScript sobre la API REST sigue abierto.
  6. Publicar una especificación OpenAPI y un endpoint de demostración alojado.
  7. Hacer que el motor de políticas y la fusión de riesgos sean revisados/auditados antes de que alguien confíe en un BLOCK de este servicio en producción - es una herramienta de seguridad, por lo que necesita el mismo escrutinio que aplica a otros.
  8. Añadir límites de capacidad por agente (alcance de delegación). Hecho - guardian/policy/capabilities.py, e integrado en DecisionEngine.evaluate() mediante un argumento de constructor opcional capability_registry (anteriormente era un módulo independiente que tenías que llamar tú mismo fuera del pipeline normal - ver examples/example_capability_limits.py, que ahora se ejecuta directamente a través de DecisionEngine). Opt-in: no pasar ningún registro (el predeterminado) y nada cambia; un operador puede otorgar a un agente específico una capacidad con alcance (tipos de acción permitidos, cadenas permitidas, límites de gasto por acción y diarios, una caducidad) sin involucrar material de clave privada. Los agentes sin concesión no se ven afectados. Este módulo nunca toca claves privadas ni la emisión de claves de sesión - eso sigue fuera de alcance, un problema categóricamente de mayor riesgo. La aplicación real de una decisión (vs. un agente que elige respetarla) sigue deliberadamente fuera de alcance. Parcialmente hecho - onchain/'s GuardianValidator es un módulo ERC-7579 que hace que una decisión sea genuinamente ineludible para cualquier cuenta inteligente ERC-4337 que lo instale, sin que Guardian tenga una clave. No gestiona claves de sesión, custodia ni creación de cuentas - solo limita la ejecución detrás de una atestación - así que esto es una pieza real y de soporte de "account abstraction", no la totalidad.
  9. Verificar la intención declarada contra los resultados de simulación decodificados. Hecho - guardian/decision/intent_verification.py detecta el caso en que un agente declara una cantidad pero el calldata real que se le entregó codifica una cantidad significativamente diferente (pero aún finita), y DecisionEngine.evaluate() ahora realmente lo llama (antes no lo hacía - el módulo y su script de ejemplo existían, pero nada en el pipeline de decisión real lo invocaba). Todavía no es una salvaguarda funcional por sí solo: comparar unidades atómicas necesita el decimals() del token, y aún no existe un proveedor de decimales. GUARDIAN_DECIMALS_PROVIDER=rpc (RpcTokenDecimalsProvider, ver guardian/intelligence/token/decimals.py) cierra eso: un eth_call real al decimals() del propio token, almacenado en caché para siempre por (cadena, token) ya que ese valor nunca puede cambiar una vez que un contrato está desplegado. Dejado en su valor predeterminado null, cada approve con una simulación exitosa de cantidad finita aún recibe un WARN honesto de "no se puede verificar sin decimales" en lugar de un BLOCK falso o una omisión silenciosa - configurar el proveedor real es lo que convierte eso en un BLOCK real ante una discrepancia genuina. Ver examples/example_intent_verification.py para la verificación que bloquea una discrepancia real, y tests/test_decision_engine.py's TestIntentVerificationWithRealDecimalsProvider para la versión de extremo a extremo conectada a través de una búsqueda de decimales real (RPC simulado) en lugar de un argumento token_decimals proporcionado manualmente.
  10. Marcar acciones que se desvían del patrón histórico de un agente. Hecho - guardian/intelligence/anomaly/analyzer.py. Distinto de la reputación (una puntuación de confianza única) y la política (límites estáticos establecidos por el operador): esto compara la intención actual contra el historial registrado de este agente específico - nuevo tipo de acción, nueva cadena, o una cantidad que es un valor atípico estadístico en comparación con lo que este agente ha hecho antes, incluso si está dentro de los límites de la política y la reputación del agente es buena. Informa honestamente "historial insuficiente" en lugar de adivinar una línea base con menos de 5 puntos de datos previos - ver tests/test_anomaly_detection.py.
  11. Situarse frente a una wallet de agente real, no solo aceptar intenciones de un llamador API genérico. Hecho para MetaMask Agent Wallet - skills/guardian-check/ es una Agent Skill estándar que un agente instala junto con la habilidad mm de MetaMask; el agente la llama antes de ejecutar cualquier comando mm que mueva fondos y solo procede con ALLOW. Probado de extremo a extremo contra una instancia uvicorn en vivo (ALLOW/WARN/BLOCK/error de configuración ejercitados de verdad, no solo afirmados) - ver la sección "Usando Guardian frente a MetaMask Agent Wallet" arriba. No existe un hook público (aún) para ejecutarse dentro del pipeline propio de MetaMask; esto funciona en la capa de orquestación del agente.

Proyectos relacionados

Mismo autor, mismo principio aplicado en otros lugares:

  • agent-guardrail - un firewall de políticas genérico para llamadas de herramientas de agentes de IA (no específico de blockchain). Publicado en PyPI, MIT, 46 pruebas.
  • x402-attest - atestaciones firmadas criptográficamente (Ed25519), verificables de forma independiente para decisiones de política de pago entre agentes. Prueba de concepto temprana.
  • open-agent-attestation - especificación abierta neutral al proveedor (JWT+EdDSA) para firmar decisiones de política de agentes, verificable por cualquiera. x402-attest arriba usa un formato personalizado; esta es la versión generalizada. Borrador v0.1.

Licencia

MIT - ver LICENSE.