El problema
Los agentes de LangChain pueden llamar a herramientas con entradas inesperadas, agotar créditos API sin límites o realizar llamadas peligrosas al sistema. La gobernanza actual ocurre en el nivel de solicitud (que el LLM puede ignorar) en lugar de en el nivel de tiempo de ejecución.
La solucion de Scavio
Envuelva cada herramienta LangChain con una capa de política determinista que bloquee las llamadas antes de la ejecución. No hay llamadas de LLM en la ruta de aplicación: comprobaciones puras de código. Políticas: llamadas máximas por sesión, validación de entradas (sin patrones de PII), validación de salidas (recuento mínimo de resultados), presupuestos de crédito y listas de bloqueo.
Antes
Antes de la aplicación de la ley, un agente de producción agotó sus créditos de SerpAPI en una sesión realizando llamadas de búsqueda en bucle. Un incidente aparte: el agente pasó la dirección de correo electrónico de un cliente como consulta de búsqueda, filtrando PII al proveedor de búsqueda. Ambos fueron capturados días después en la revisión de registros.
Después
Después de agregar el contenedor estilo ShadowAudit, el agente tiene un límite de 10 llamadas de búsqueda por sesión. Los patrones de PII (correo electrónico, teléfono, SSN) están bloqueados en las consultas de búsqueda. El presupuesto de crédito se rastrea por sesión. El agente intenta bloquear 2,3 llamadas por cada 100 sesiones, todas detectadas antes de la ejecución.
Para quien es
Desarrolladores de LangChain que implementan agentes en producción y necesitan una gestión determinista del tiempo de ejecución sobre las llamadas de herramientas, los presupuestos de crédito y la seguridad de los datos.
Beneficios clave
- Aplicación determinista: no hay LLM en el camino de la gobernanza
- Bloquea llamadas peligrosas antes de que se ejecuten
- Seguimiento del uso de herramientas por sesión para controlar costos
- La detección de PII evita la filtración de datos a los proveedores de búsqueda
- Funciona como contenedor en cualquier herramienta LangChain
Ejemplo en Python
import re
from typing import Callable
class ToolPolicy:
def __init__(self, max_calls: int = 10, block_pii: bool = True):
self.max_calls = max_calls
self.block_pii = block_pii
self.call_count = 0
self.pii_patterns = [
re.compile(r'[\w.-]+@[\w.-]+\.\w+'), # email
re.compile(r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b'), # phone
]
def enforce(self, query: str) -> str | None:
self.call_count += 1
if self.call_count > self.max_calls:
return f'Blocked: max {self.max_calls} calls exceeded'
if self.block_pii:
for pattern in self.pii_patterns:
if pattern.search(query):
return 'Blocked: PII detected in query'
return None
def wrap_tool(fn: Callable, policy: ToolPolicy) -> Callable:
def wrapped(query: str) -> str:
block = policy.enforce(query)
if block:
return block
return fn(query)
return wrapped
# Usage:
policy = ToolPolicy(max_calls=10, block_pii=True)
# search_tool = wrap_tool(original_search, policy)Ejemplo en JavaScript
class ToolPolicy {
constructor(maxCalls = 10) {
this.maxCalls = maxCalls;
this.callCount = 0;
this.piiPatterns = [/[\w.-]+@[\w.-]+\.\w+/, /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/];
}
enforce(query) {
this.callCount++;
if (this.callCount > this.maxCalls) return `Blocked: max ${this.maxCalls} calls exceeded`;
if (this.piiPatterns.some(p => p.test(query))) return 'Blocked: PII detected';
return null;
}
}
function wrapTool(fn, policy) {
return async (query) => {
const block = policy.enforce(query);
if (block) return block;
return fn(query);
};
}
const policy = new ToolPolicy(10);
// const safeTool = wrapTool(originalSearch, policy);Plataformas utilizadas
Búsqueda web con grafo de conocimiento, PAA y resúmenes de IA