Policy Layer
Controles de gasto sin custodia para billeteras de agentes de IA: aplica límites, listas permitidas e interruptores de seguridad antes de que se ejecuten las transacciones.
Documentación
Tu agente de IA acaba de hacer su cargo número 47 de Stripe en el día. Cada uno parecía razonable por separado — $12 aquí, $35 allá — pero el total acumulado llegó a $4,200 antes de que alguien lo notara. El agente estaba haciendo exactamente lo que se le dijo: procesar pedidos. Simplemente nunca se detuvo.
Agregar controles de gasto a tu agente MCP evita exactamente este escenario. Los servidores MCP como Stripe, AWS y Twilio dan a los agentes acceso directo a herramientas que cuestan dinero real. El agente no sabe que tiene un presupuesto. El servidor MCP no impone uno. Y la indicación del sistema que dice “no gastes más de $500 por día” es una sugerencia, no una restricción.
PolicyLayer resuelve esto colocándose entre el agente y el servidor MCP como un proxy transparente. Cada solicitud tools/call pasa a través de él, se evalúa contra un archivo de políticas YAML y se reenvía o se bloquea. El agente no sabe que PolicyLayer existe — mismas herramientas, mismos esquemas, misma interfaz.
Así es como se configura.
La Arquitectura
┌──────────┐ ┌─────────────┐ ┌────────────┐
│ LLM/AI │──────>│ PolicyLayer │──────>│ MCP Server │
│ Client │<──────│ (proxy) │<──────│ (upstream) │
└──────────┘ └─────────────┘ └────────────┘
│
┌────┴────┐
│ Policy │
│ Engine │
└────┬────┘
┌────┴────┐
│ State │
│ Store │
└─────────┘
PolicyLayer proxifica el tráfico MCP sobre HTTP. Intercepta las solicitudes tools/call, las evalúa contra tu política y devuelve un mensaje de denegación si alguna regla falla. El almacén de estado persiste los contadores entre reinicios para que tus límites de gasto diario sobrevivan al reciclaje de procesos.
Paso 1: Escanear el servidor MCP
Antes de escribir políticas, necesitas saber qué herramientas están disponibles. PolicyLayer se conecta a cualquier servidor MCP registrado, descubre sus herramientas y genera un andamiaje YAML comentado que lista cada herramienta con sus parámetros, agrupadas por categoría. Es un punto de partida — todo está permitido por defecto hasta que agregues reglas.
Paso 2: Agregar un límite por transacción
El control de gasto más básico es limitar una sola transacción. Si tu agente puede llamar a create_charge, probablemente no quieras que cree cargos de $10,000:
version: "1"
description: "Stripe spending controls"
tools:
create_charge:
rules:
- name: "max single charge"
conditions:
- path: "args.amount"
op: "lte"
value: 50000
on_deny: "Single charge cannot exceed $500.00"
Esta regla verifica el argumento amount en cada llamada a create_charge. Si excede 50000 (Stripe usa centavos), la llamada se bloquea y el agente recibe el mensaje de denegación. El agente puede entonces decidir qué hacer — pedir aprobación al usuario, dividir la transacción o abandonar la tarea.
El detalle clave: esta verificación ocurre en la capa de transporte, antes de que la solicitud llegue a Stripe. El cargo nunca se crea. No hay reembolso que procesar, ni pago fallido que conciliar. Esto es aplicación determinista de políticas — la misma entrada siempre produce el mismo resultado.
Paso 3: Agregar un límite de gasto diario
Los límites por transacción no previenen la acumulación. Un agente que hace 200 cargos de $50 cada uno superará un límite de $500 por cargo mientras acumula $10,000 en gasto total. Necesitas seguimiento acumulativo.
PolicyLayer maneja esto con contadores con estado:
tools:
create_charge:
rules:
- name: "max single charge"
conditions:
- path: "args.amount"
op: "lte"
value: 50000
on_deny: "Single charge cannot exceed $500.00"
- name: "daily spend cap"
conditions:
- path: "state.create_charge.daily_spend"
op: "lte"
value: 1000000
on_deny: "Daily spending cap of $10,000.00 reached"
state:
counter: "daily_spend"
window: "day"
increment_from: "args.amount"
El bloque state crea un contador llamado daily_spend que se reinicia a medianoche UTC. En cada llamada permitida a create_charge, el contador se incrementa por lo que sea args.amount. Antes de la siguiente llamada, la condición verifica si el total acumulado excede el límite.
El campo increment_from es lo que hace que esto funcione específicamente para gastos. En lugar de contar llamadas (el valor predeterminado), suma los montos reales en dólares. Un cargo de $50 incrementa en 5000, un cargo de $200 en 20000. Cuando el total acumulado excedería 1000000 ($10,000), se deniegan cargos adicionales.
Los contadores persisten en el almacén de estado. Si reinicias PolicyLayer, el total diario continúa donde quedó. Y el modelo de dos fases significa que las llamadas ascendentes fallidas no consumen cuota — si Stripe devuelve un error, el incremento se revierte.
Paso 4: Restringir monedas y argumentos
Los controles de gasto no se tratan solo de montos. Puede que quieras restringir en qué monedas un agente puede cobrar, en qué regiones puede operar o qué productos puede comprar:
- name: "allowed currencies"
conditions:
- path: "args.currency"
op: "in"
value: ["usd", "eur"]
on_deny: "Only USD and EUR charges are permitted"
Esto usa el operador in para verificar contra una lista blanca. Puedes combinar múltiples condiciones en una sola regla — se combinan con AND:
- name: "safe charge"
conditions:
- path: "args.amount"
op: "lte"
value: 50000
- path: "args.currency"
op: "in"
value: ["usd", "eur"]
on_deny: "Charge must be under $500 and in USD or EUR"
Ambas condiciones deben cumplirse. Si alguna falla, toda la llamada se deniega.
Paso 5: Bloquear operaciones destructivas
Algunas herramientas nunca deberían ser llamadas por un agente, independientemente de los argumentos. Eliminar clientes, borrar bases de datos, quitar infraestructura — estas son operaciones solo para humanos:
hide:
- delete_customer
- delete_product
- delete_invoice
tools:
delete_subscription:
rules:
- name: "block subscription deletion"
action: "deny"
on_deny: "Subscription deletion is not permitted via AI agents"
Hay dos enfoques aquí. La lista hide elimina herramientas de la vista del agente por completo — se eliminan de las respuestas tools/list, por lo que el agente nunca sabe que existen. Esto ahorra tokens de ventana de contexto y evita que el agente siquiera intente la llamada.
Para herramientas que quieres que el agente vea pero no use, usa action: "deny". La herramienta aparece en tools/list, pero cualquier llamada se bloquea incondicionalmente con el mensaje de denegación.
Paso 6: Agregar un límite de tasa global
Incluso con controles de gasto por herramienta, quieres un respaldo. Un límite de tasa global limita el número total de llamadas a herramientas por ventana de tiempo en todas las herramientas:
"*":
rules:
- name: "global rate limit"
rate_limit: 60/minute
El comodín "*" se aplica a cada llamada de herramienta. Esto previene bucles descontrolados donde un agente llama a herramientas cientos de veces por minuto, independientemente de si cada llamada individual pasa sus reglas específicas. Para más sobre estrategias de limitación de tasa, consulta nuestra guía práctica.
Paso 7: Conéctalos
Enruta tu servidor MCP de Stripe a través de PolicyLayer — apunta tu cliente MCP a la URL de la puerta de enlace con un token de concesión por persona, y la política anterior se ejecuta en cada llamada antes de que llegue a Stripe:
{
"mcpServers": {
"stripe": {
"url": "https://proxy.policylayer.com/mcp/<server-uuid>/",
"headers": { "Authorization": "Bearer <grant-token>" }
}
}
}
Defines y ajustas la política en el panel de PolicyLayer — sin proxy local que instalar o ejecutar.
El agente se conecta a PolicyLayer pensando que es el servidor MCP de Stripe. PolicyLayer reenvía todo excepto las violaciones de política.
La Política Completa
Aquí está la política completa que combina todas las reglas anteriores:
Haz clic para expandir el YAML de la política completa
version: "1"
description: "Stripe MCP server spending controls"
hide:
- delete_customer
- delete_product
- delete_invoice
tools:
create_charge:
rules:
- name: "max single charge"
conditions:
- path: "args.amount"
op: "lte"
value: 50000
on_deny: "Single charge cannot exceed $500.00"
- name: "daily spend cap"
conditions:
- path: "state.create_charge.daily_spend"
op: "lte"
value: 1000000
on_deny: "Daily spending cap of $10,000.00 reached"
state:
counter: "daily_spend"
window: "day"
increment_from: "args.amount"
- name: "allowed currencies"
conditions:
- path: "args.currency"
op: "in"
value: ["usd", "eur"]
on_deny: "Only USD and EUR charges are permitted"
create_refund:
rules:
- name: "refund amount cap"
conditions:
- path: "args.amount"
op: "lte"
value: 10000
on_deny: "Refunds over $100.00 require manual processing"
- name: "daily refund count"
rate_limit: 10/day
on_deny: "Daily refund limit (10) reached"
"*":
rules:
- name: "global rate limit"
rate_limit: 60/minute
Recarga en caliente
Las políticas se pueden recargar en caliente. Edita la política en el panel mientras PolicyLayer está en ejecución y los cambios se aplican de inmediato — sin reinicio, sin conexiones caídas. Esto significa que puedes ajustar los límites en respuesta al comportamiento observado sin interrumpir al agente.
PolicyLayer también valida las políticas antes de que entren en vigor, detectando errores de sintaxis, operadores inválidos, contadores faltantes y conflictos lógicos antes de que lleguen a producción.
Lo que ve el agente
Cuando se deniega una llamada, el agente recibe un mensaje como:
[POLICYLAYER POLICY DENIED] Daily spending cap of $10,000.00 reached
Esto es deliberado. El agente sabe por qué falló la llamada y puede adaptar su comportamiento — informar al usuario, intentar un monto menor o esperar hasta que se reinicie la ventana. Es un bucle de retroalimentación, no un fallo silencioso.
Más allá de Stripe
El mismo patrón funciona para cualquier servidor MCP que toque dinero o recursos. Controles de costos de AWS, límites de mensajes de Twilio, topes de escritura en bases de datos, presupuestos de llamadas a API — si la herramienta tiene argumentos que puedes validar y llamadas que puedes contar, PolicyLayer puede imponer límites sobre ella.
Preguntas frecuentes
¿Cómo persisten los controles de gasto de MCP entre reinicios?
PolicyLayer almacena el estado de los contadores en un almacén de estado persistente. Cuando reinicias PolicyLayer, los totales de gasto diario, los contadores de límite de tasa y todo el seguimiento con estado continúan exactamente donde quedaron. No se pierde ningún estado.
¿Pueden los agentes MCP eludir los límites de gasto?
No a través de PolicyLayer. Debido a que los controles de gasto se aplican en la capa de transporte — entre el agente y el servidor MCP — el agente no tiene forma de eludirlos. El agente ni siquiera sabe que PolicyLayer existe. Ve las mismas herramientas y esquemas, pero cada solicitud tools/call se evalúa contra la política antes de llegar al servidor ascendente.
¿Qué sucede cuando un agente MCP alcanza un límite de gasto?
El agente recibe un mensaje de denegación que explica por qué se bloqueó la llamada, por ejemplo, [POLICYLAYER POLICY DENIED] Daily spending cap of $10,000.00 reached. El agente puede entonces adaptarse — informar al usuario, intentar un monto menor o esperar hasta que se reinicie la ventana de tiempo. El servidor MCP ascendente nunca recibe la solicitud bloqueada.