TL;DR
Dejas de "cuidar" agentes de IA construyendo tres cosas: barandillas de seguridad (restricciones que previenen fallos catastróficos), observabilidad (registros y métricas que te dicen qué pasó) y puntos de control (pausas automáticas donde los humanos verifican decisiones). Configura esto una vez, y tus agentes podrán ejecutarse de forma autónoma durante horas en lugar de minutos. Herramientas como Apidog ayudan al permitirte definir contratos de API que los agentes no pueden violar, convirtiendo tu capa de API en una red de seguridad.
Introducción
La semana pasada vi a un desarrollador pasar 4 horas supervisando un agente de IA que se suponía le ahorraría tiempo. Cada pocos minutos, lo interrumpía, corregía un error y lo reiniciaba. Al final, había hecho más trabajo manual que si hubiera escrito el código él mismo.
Este es el problema de la "canguro", y es la razón número 1 por la que los agentes de IA no cumplen su promesa. Las herramientas funcionan. Los modelos son capaces. Pero la mayoría de los equipos nunca superan la fase de supervisión constante.
Esto es lo que está pasando: la mayoría de las configuraciones de agentes de IA tratan al LLM como un desarrollador junior que necesita ayuda en cada tarea. Pero los LLM no son juniors. Son más bien como becarios extremadamente rápidos, ocasionalmente alucinantes, que harán con confianza lo incorrecto si no estableces límites.
Define contratos de API que tus agentes de IA puedan seguir
Al final de esta guía, tendrás:
- Un modelo mental para pensar sobre la autonomía de los agentes
- Patrones concretos para barandillas de seguridad, observabilidad y puntos de control
- Ejemplos de código que puedes copiar en tus proyectos hoy mismo
- Una lista de verificación para evaluar si un agente está listo para ejecutarse sin supervisión
Por qué los agentes necesitan supervisión constante
Los agentes de IA fallan de maneras predecibles. Comprender estos modos de fallo es el primer paso para solucionarlos.
Modo de fallo 1: Desviación del alcance (Scope creep)
Le pides a un agente que "añada autenticación al punto final de la API". Añade autenticación. Luego añade limitación de velocidad. Luego refactoriza el esquema de la base de datos. Luego elimina lo que cree que son archivos "no utilizados", que resultan ser importantes.
El agente siguió adelante porque nadie le dijo que se detuviera. Los LLM no tienen un sentido innato de "hecho". Seguirán haciendo cambios hasta que alcancen un límite de tokens o tú los interrumpas.
Modo de fallo 2: Abstracciones incorrectas
Un agente encargado de "mejorar el manejo de errores" podría añadir bloques try-catch por todas partes. Técnicamente correcto. Prácticamente terrible. El código se vuelve ilegible, el registro es inconsistente y los casos de error reales no se manejan.
El agente entendió la solicitud literalmente pero no captó la intención. Sin ejemplos de un buen manejo de errores, recurrió a la interpretación más obvia (y peor).
Modo de fallo 3: Fallos en cascada
Un agente comete un pequeño error en el paso 1. Para el paso 10, ese error se ha propagado a través de cada decisión subsiguiente. Lo que comenzó como un error tipográfico en un nombre de función se convierte en una API rota, pruebas rotas y un desarrollador confundido tratando de averiguar qué salió mal.
Este es el modo de fallo más peligroso porque el agente no sabe que falló. Cada paso parece razonable de forma aislada. Solo el resultado final revela el problema.
Modo de fallo 4: Agotamiento de recursos
Si no se supervisan, algunos agentes entrarán en bucle indefinidamente. Reintentarán llamadas a la API fallidas sin límite, generarán nuevos sub-agentes sin restricción o seguirán generando código hasta que alcancen tu límite de facturación.
Sin restricciones de recursos, los agentes no saben cuándo detenerse.
El marco de autonomía: barandillas de seguridad, observabilidad, puntos de control
Resuelves estos problemas con tres capas. Piénsalas como una pirámide: barandillas de seguridad en la base (previniendo fallos), observabilidad en el medio (detectando fallos) y puntos de control en la cima (recuperándose de fallos).
Capa 1: Barandillas de seguridad (prevención)
Las barandillas de seguridad son restricciones que previenen fallos catastróficos. Son reglas que tu agente no puede romper, aplicadas por código, no por instrucciones.
Restricciones duras mediante código:
# No: Confíes en que el agente siga las instrucciones
agent.run("Only modify files in the src/ directory")
# Sí: Aplica las restricciones en el código
import os
from pathlib import Path
ALLOWED_DIRECTORIES = {"src", "tests", "docs"}
def validate_file_path(path: str) -> bool:
"""El agente no puede escribir fuera de los directorios permitidos."""
abs_path = Path(path).resolve()
return any(
str(abs_path).startswith(str(Path(d).resolve()))
for d in ALLOWED_DIRECTORIES
)
# Usar en las operaciones de archivo de tu agente
def agent_write_file(path: str, content: str):
if not validate_file_path(path):
raise ValueError(f"Cannot write to {path}: outside allowed directories")
with open(path, 'w') as f:
f.write(content)
Restricciones de esquema de API:
Cuando tu agente llama a APIs, usa esquemas para prevenir solicitudes malformadas. Aquí es donde Apidog brilla. Define tu contrato de API una vez, y tu agente no podrá enviar datos con una forma incorrecta.
// apidog-schema.ts
export const CreateUserSchema = {
type: 'object',
required: ['email', 'name'],
properties: {
email: { type: 'string', format: 'email' },
name: { type: 'string', minLength: 1, maxLength: 100 },
role: { type: 'string', enum: ['user', 'admin', 'guest'] }
},
additionalProperties: false
}
// El agente debe validar antes de llamar a la API
function validateRequest(schema: object, data: unknown): void {
const valid = ajv.validate(schema, data)
if (!valid) {
throw new Error(`Invalid request: ${JSON.stringify(ajv.errors)}`)
}
}
Restricciones de presupuesto:
import time
from dataclasses import dataclass
@dataclass
class AgentBudget:
max_steps: int = 50
max_tokens: int = 100000
max_time_seconds: int = 600 # 10 minutos
max_api_calls: int = 100
class BudgetEnforcer:
def __init__(self, budget: AgentBudget):
self.budget = budget
self.start_time = time.time()
self.steps = 0
self.tokens_used = 0
self.api_calls = 0
def check(self) -> bool:
"""Devuelve False si el presupuesto ha sido excedido."""
elapsed = time.time() - self.start_time
if self.steps >= self.budget.max_steps:
raise RuntimeError(f"Step limit reached: {self.steps}")
if self.tokens_used >= self.budget.max_tokens:
raise RuntimeError(f"Token limit reached: {self.tokens_used}")
if elapsed >= self.budget.max_time_seconds:
raise RuntimeError(f"Time limit reached: {elapsed:.0f}s")
if self.api_calls >= self.budget.max_api_calls:
raise RuntimeError(f"API call limit reached: {self.api_calls}")
return True
def record_step(self, tokens: int, api_calls: int = 0):
self.steps += 1
self.tokens_used += tokens
self.api_calls += api_calls
self.check()
Capa 2: Observabilidad (detección)
Cuando los agentes se ejecutan durante horas, necesitas saber qué están haciendo sin observar cada paso. La observabilidad te proporciona una línea de tiempo de las decisiones.
Registro estructurado:
import json
from datetime import datetime
from typing import Any
class AgentLogger:
def __init__(self, log_file: str = "agent_trace.jsonl"):
self.log_file = log_file
self.entries = []
def log(self, event: str, data: dict[str, Any] | None = None):
entry = {
"timestamp": datetime.utcnow().isoformat(),
"event": event,
"data": data or {}
}
self.entries.append(entry)
# Añadir al archivo inmediatamente (para no perder registros en caso de fallo)
with open(self.log_file, 'a') as f:
f.write(json.dumps(entry) + '\n')
def log_decision(self, decision: str, reasoning: str, confidence: float):
"""Registra cuando el agente toma una decisión significativa."""
self.log("decision", {
"decision": decision,
"reasoning": reasoning,
"confidence": confidence
})
def log_action(self, action: str, params: dict, result: str):
"""Registra las acciones del agente y sus resultados."""
self.log("action", {
"action": action,
"params": params,
"result": result[:200] # Truncar resultados largos
})
def log_error(self, error: str, context: dict):
"""Registra errores con contexto completo."""
self.log("error", {
"error": error,
"context": context
})
# Uso en el agente
logger = AgentLogger()
logger.log_decision(
decision="Add rate limiting to API",
reasoning="Current endpoint has no protection against abuse",
confidence=0.85
)
logger.log_action(
action="write_file",
params={"path": "src/middleware/rate-limit.ts"},
result="Successfully wrote 45 lines"
)
Panel de métricas:
Para agentes de larga duración, querrás métricas agregadas, no solo registros individuales.
from collections import Counter
from dataclasses import dataclass, field
@dataclass
class AgentMetrics:
actions_taken: Counter = field(default_factory=Counter)
files_modified: list[str] = field(default_factory=list)
api_calls: dict[str, int] = field(default_factory=dict)
errors: list[str] = field(default_factory=list)
decisions_by_confidence: dict[str, int] = field(default_factory=lambda: {
"high (>0.9)": 0,
"medium (0.7-0.9)": 0,
"low (<0.7)": 0
})
def record_action(self, action: str):
self.actions_taken[action] += 1
def record_file_modification(self, path: str):
if path not in self.files_modified:
self.files_modified.append(path)
def record_api_call(self, endpoint: str):
self.api_calls[endpoint] = self.api_calls.get(endpoint, 0) + 1
def record_error(self, error: str):
self.errors.append(error)
def record_decision(self, confidence: float):
if confidence > 0.9:
self.decisions_by_confidence["high (>0.9)"] += 1
elif confidence >= 0.7:
self.decisions_by_confidence["medium (0.7-0.9)"] += 1
else:
self.decisions_by_confidence["low (<0.7)"] += 1
def summary(self) -> str:
return f"""
Agent Metrics Summary
=====================
Actions: {dict(self.actions_taken)}
Files modified: {len(self.files_modified)}
API calls: {self.api_calls}
Errors: {len(self.errors)}
Decisions by confidence: {self.decisions_by_confidence}
"""
Capa 3: Puntos de control (recuperación)
Los puntos de control son pausas automáticas donde el agente espera la verificación humana. Te permiten detectar problemas temprano sin supervisión constante.
Puntos de control automáticos:
from enum import Enum
from typing import Callable
class CheckpointTrigger(Enum):
BEFORE_FILE_WRITE = "before_file_write"
BEFORE_API_CALL = "before_api_call"
BEFORE_GIT_COMMIT = "before_git_commit"
BEFORE_DELETE = "before_delete"
AFTER_N_STEPS = "after_n_steps"
@dataclass
class Checkpoint:
trigger: CheckpointTrigger
description: str
data: dict
requires_approval: bool = True
class CheckpointManager:
def __init__(self, auto_approve: set[CheckpointTrigger] | None = None):
self.auto_approve = auto_approve or set()
self.pending: list[Checkpoint] = []
def create_checkpoint(
self,
trigger: CheckpointTrigger,
description: str,
data: dict
) -> bool:
"""Devuelve True si es aprobado, False si es rechazado."""
# Aprobar automáticamente ciertos desencadenantes
if trigger in self.auto_approve:
return True
checkpoint = Checkpoint(
trigger=trigger,
description=description,
data=data
)
self.pending.append(checkpoint)
# En un sistema real, esto notificaría al humano y esperaría
# Por ahora, devolvemos False para pausar la ejecución
return False
def approve(self, checkpoint_id: int) -> None:
"""El humano aprueba un punto de control pendiente."""
if 0 <= checkpoint_id < len(self.pending):
self.pending.pop(checkpoint_id)
def reject(self, checkpoint_id: int) -> None:
"""El humano rechaza un punto de control pendiente."""
raise RuntimeError(f"Checkpoint rejected: {self.pending[checkpoint_id]}")
# Uso en el agente
checkpoints = CheckpointManager(
auto_approve={CheckpointTrigger.BEFORE_FILE_WRITE} # Confiar en las escrituras de archivos
)
# Antes de una acción destructiva
if not checkpoints.create_checkpoint(
trigger=CheckpointTrigger.BEFORE_DELETE,
description="About to delete src/legacy/ directory",
data={"path": "src/legacy/", "files": ["old_handler.ts", "deprecated.ts"]}
):
# Esperar la aprobación humana
agent.pause("Waiting for approval to delete files")
Construyendo agentes autónomos con Apidog
Cuando tu agente de IA interactúa con APIs, el mayor riesgo son las solicitudes malformadas que causan fallos posteriores. Apidog ayuda al permitirte definir esquemas de API exactos que tu agente debe seguir.
Configuración de contratos de API:
- Importa o define tu especificación OpenAPI en Apidog
- Genera código cliente con validación integrada
- Dale a tu agente el cliente validado en lugar de HTTP crudo
// En lugar de dejar que el agente llame a las APIs directamente
const response = await fetch('/api/users', {
method: 'POST',
body: JSON.stringify(data) // Sin validación
})
// Dale al agente un cliente validado
import { UsersApi } from './generated/apidog-client'
const usersApi = new UsersApi()
// El agente solo puede enviar solicitudes válidas - esquema aplicado
const response = await usersApi.createUser({
email: 'user@example.com',
name: 'Test User',
role: 'user' // Debe ser un valor de enumeración válido
})
Esto convierte tu capa de API en una barandilla de seguridad. El agente literalmente no puede enviar datos inválidos porque el cliente los rechaza antes de que la solicitud salga.
Genera clientes de API validados para tus agentes de IA
Patrones probados y errores comunes
Patrón 1: El sándwich de aprobación
Para operaciones arriesgadas, requiere aprobación antes Y después.
def risky_operation(agent, operation):
# Pre-aprobación
if not agent.checkpoint(f"About to: {operation.description}"):
return "Cancelled by user"
# Realizar la operación
result = operation.execute()
# Post-aprobación (verificar el resultado)
if not agent.checkpoint(f"Verify result of: {operation.description}"):
operation.rollback()
return "Rolled back by user"
return result
Patrón 2: Umbrales de confianza
No permitas que los agentes actúen sobre decisiones de baja confianza.
MIN_CONFIDENCE = 0.75
def agent_decide(options: list[dict]) -> dict:
best = max(options, key=lambda x: x.get('confidence', 0))
if best['confidence'] < MIN_CONFIDENCE:
# Escalar a humano
return {
'action': 'escalate',
'reason': f"Best option has confidence {best['confidence']:.2f} < {MIN_CONFIDENCE}",
'options': options
}
return best
Patrón 3: Operaciones idempotentes
Diseña las acciones de tu agente para que sean repetibles sin efectos secundarios.
import hashlib
def idempotent_write(path: str, content: str) -> bool:
"""Solo escribe si el contenido ha cambiado."""
content_hash = hashlib.sha256(content.encode()).hexdigest()
existing_hash = None
if os.path.exists(path):
with open(path, 'r') as f:
existing_hash = hashlib.sha256(f.read().encode()).hexdigest()
if content_hash == existing_hash:
logger.log_action("write_file", {"path": path}, "Skipped - no changes")
return False
with open(path, 'w') as f:
f.write(content)
logger.log_action("write_file", {"path": path}, f"Wrote {len(content)} bytes")
return True
Errores comunes a evitar
Confiar en las instrucciones como restricciones. "No borres archivos" en una instrucción no es una restricción. Los permisos de archivo sí lo son.
No tener un plan de reversión. Cuando un agente comete un error, necesitas deshacerlo. Si no usas git o copias de seguridad, estás confiando al agente acciones irrecuperables.
**Ignorar las puntuaciones de confianza. La mayoría de los LLM dan puntuaciones de confianza o se les puede pedir. Baja confianza = pausar y preguntar a un humano.
**Monitorización excesiva. Si estás observando cada paso, no has construido un sistema autónomo. Has construido un sistema manual lento.
Especificar de forma insuficiente el éxito. El agente necesita saber cuándo ha terminado. "Corregir el error" no tiene una condición final. "Corregir el error Y todas las pruebas pasan" sí la tiene.
Alternativas y comparaciones
| Enfoque | Autonomía | Riesgo | Mejor para |
|---|---|---|---|
| Codificación manual | Ninguna | Bajo | Trabajo complejo y crítico |
| Programación en pareja con IA | Baja | Bajo | Aprendizaje, exploración |
| Agentes supervisados | Media | Medio | Tareas rutinarias |
| Agentes autónomos con barandillas | Alta | Controlado | Operaciones masivas, migraciones |
| Agentes totalmente autónomos | Muy alta | Alto | Flujos de trabajo confiables y bien probados |
La mayoría de los equipos deberían aspirar a "autónomos con barandillas de seguridad". Es el punto óptimo donde obtienes el 80% del ahorro de tiempo con el 10% del riesgo.
Casos de uso en el mundo real
Migración de bases de código. Un equipo utilizó un agente autónomo para migrar 200 puntos finales de API de REST a GraphQL. Las barandillas de seguridad evitaron cambios en el esquema. Los puntos de control requirieron aprobación antes de eliminar los puntos finales antiguos. La migración tomó 3 días en lugar de 3 semanas, con cero incidentes en producción.
Generación de documentación. Un agente genera automáticamente documentación de API a partir del código. Las barandillas de seguridad aseguran que solo lea de directorios específicos. Los puntos de control pausan antes de publicar. El equipo revisa una vez a la semana en lugar de escribir la documentación manualmente.
Cobertura de pruebas. Un agente analiza el código y escribe pruebas faltantes. Las restricciones de presupuesto evitan la generación descontrolada de pruebas. Los umbrales de confianza marcan las pruebas inciertas para revisión humana. La cobertura mejoró del 60% al 85% en un mes.
Conclusión
Esto es lo que has aprendido:
- Los agentes de IA fallan de maneras predecibles: desviación del alcance, abstracciones incorrectas, fallos en cascada, agotamiento de recursos
- Tres capas resuelven la mayoría de los problemas: barandillas de seguridad (prevención), observabilidad (detección), puntos de control (recuperación)
- Las barandillas de seguridad son código, no instrucciones. Aplica las restricciones de forma programática.
- La observabilidad significa registros y métricas estructurados, no observar cada paso
- Los puntos de control permiten a los humanos verificar decisiones sin supervisión constante
- Los esquemas de API de Apidog convierten tu capa de API en una barandilla de seguridad
Tus próximos pasos:
- Identifica tu tarea más repetitiva asistida por IA
- Define barandillas de seguridad: ¿qué nunca debe hacer el agente?
- Añade registro estructurado para ver qué está pasando
- Crea puntos de control para operaciones de alto riesgo
- Déjalo ejecutar durante 30 minutos y verifica los registros
El objetivo no es eliminar a los humanos del ciclo. Es colocar a los humanos en el lugar correcto del ciclo: tomando decisiones de alto nivel en lugar de corregir errores de bajo nivel.
Construye barandillas de seguridad de API para tus agentes de IA - gratis
Preguntas Frecuentes
¿Cuál es la diferencia entre un agente de IA y un asistente de IA?Un asistente responde a tus solicitudes y espera tu próxima instrucción. Un agente toma un objetivo y planifica y ejecuta pasos de forma autónoma para lograrlo. Los asistentes te necesitan en cada ciclo. Los agentes se ejecutan hasta que llegan a un punto de control o terminan.
¿Cómo sé si mi agente está listo para ejecutarse de forma autónoma?Ejecútalo en modo supervisado durante 10 sesiones. Rastrea cada vez que tuviste que intervenir. Si las intervenciones caen por debajo de 2 por sesión y todas fueron menores (aclaraciones, no correcciones), está listo. Si las intervenciones son frecuentes o requieren deshacer trabajo, añade más barandillas de seguridad.
¿Cuál es el mayor riesgo con los agentes autónomos?Fallos en cascada que el agente no reconoce. Un pequeño error al principio se convierte en un gran problema más tarde, y el agente sigue adelante porque cada paso parece razonable de forma aislada. Los puntos de control rompen estas cascadas al forzar la verificación.
¿Puedo usar estos patrones con cualquier LLM?Sí. Los patrones (barandillas de seguridad, observabilidad, puntos de control) son independientes del modelo. Funcionan con Claude, GPT-4, Gemini o cualquier otro modelo. Los detalles específicos de implementación pueden variar, pero los conceptos se transfieren.
¿Cuánto ralentiza la observabilidad al agente?Negligible. Escribir en un archivo de registro toma microsegundos. La ralentización proviene de los puntos de control que esperan la entrada humana. Para ejecuciones verdaderamente autónomas, solo se hacen puntos de control en momentos de alto riesgo, no en cada paso.
¿Qué pasa si el agente toma una decisión con la que no estoy de acuerdo?Para eso son los puntos de control. Cuando veas una decisión con la que no estás de acuerdo, rechaza el punto de control. El agente retrocede o intenta un enfoque diferente. Mejor aún: incluye tus preferencias en las instrucciones del agente para que aprenda tu estilo con el tiempo.
¿Debería empezar con agentes supervisados o autónomos?Siempre empieza supervisado. Ejecuta el agente con puntos de control en cada acción significativa hasta que confíes en él. Retira gradualmente los puntos de control para acciones de bajo riesgo. Esto genera confianza incrementalmente en lugar de arriesgar un fallo catastrófico en tu primera ejecución autónoma.
¿Cómo ayuda Apidog específicamente con los agentes de IA?Apidog genera clientes de API validados a partir de tus esquemas. Cuando un agente utiliza estos clientes, las solicitudes malformadas son rechazadas antes de que lleguen a tu backend. Esto previene toda una clase de fallos en los que el agente envía la forma de datos incorrecta o valores inválidos.
