TL;DR
Deja de supervisar manualmente agentes de IA implementando tres componentes: barandillas de seguridad (restricciones programáticas que previenen fallos críticos), observabilidad (logs y métricas estructurados para saber qué sucede) y puntos de control (pausas automáticas para revisión humana). Configura estos mecanismos una sola vez y tus agentes podrán operar de forma autónoma durante horas. Herramientas como Apidog te permiten definir contratos de API que los agentes no pueden violar, convirtiendo tu capa de API en una red segura.
Introducción
La semana pasada observé a un desarrollador pasar 4 horas supervisando un agente de IA que se suponía debía ahorrarle tiempo. Cada pocos minutos lo detenía para corregir errores y reiniciarlo. Al final, realizó más trabajo manual que si hubiera escrito el código él mismo.
Este es el problema “canguro” y la razón principal por la que los agentes de IA no cumplen su promesa de autonomía. Las herramientas funcionan, los modelos son capaces, pero la mayoría de equipos nunca superan la fase de supervisión constante.
El error común: la mayoría de las implementaciones tratan al LLM como un desarrollador junior que necesita ayuda continua. Pero los LLM no son juniors; son becarios súper rápidos, a veces alucinados, que harán cualquier cosa a menos que pongas límites.
💡 Tip: Si estás construyendo APIs o trabajando con agentes de IA que llaman APIs, Apidog te ayuda a definir estos límites. Especificando esquemas exactos de solicitud/respuesta, creas contratos que los agentes no pueden violar accidentalmente. Es como darle a tu agente un mapa en vez de dejarlo deambular.
Define contratos de API que tus agentes de IA puedan seguir.
Al finalizar esta guía, obtendrás:
- Un modelo mental sobre la autonomía de los agentes
- Patrones concretos para barandillas de seguridad, observabilidad y puntos de control
- Ejemplos de código listos para usar
- Una checklist para evaluar si un agente está listo para operar sin supervisión
Por qué los agentes necesitan supervisión constante
Los agentes de IA fallan de formas predecibles. Entender estos modos de fallo es el primer paso para corregirlos.
Modo de fallo 1: Desviación del alcance (Scope creep)
Pides al agente: “añade autenticación al endpoint de la API”. Añade autenticación, luego limitación de velocidad, después refactoriza el esquema de la base de datos y elimina archivos “no usados” que resultan ser importantes. El agente no sabe cuándo parar. Los LLMs carecen de noción innata de “he terminado”.
Modo de fallo 2: Abstracciones incorrectas
Un agente encargado de “mejorar el manejo de errores” podría envolver todo en bloques try-catch. Técnicamente correcto, pero el código se vuelve ilegible y los verdaderos errores no se manejan. El agente interpreta literalmente la instrucción sin captar la intención.
Modo de fallo 3: Fallos en cascada
Un pequeño error en el paso 1 puede propagarse hasta romper APIs y pruebas en el paso 10. El agente no detecta el fallo porque cada paso parece razonable de forma aislada.
Modo de fallo 4: Agotamiento de recursos
Sin control, algunos agentes entran en bucles infinitos, reintentando APIs o generando sub-agentes hasta agotar recursos o presupuesto.
El marco de autonomía: barandillas de seguridad, observabilidad y puntos de control
Resuelve estos problemas con tres capas: barandillas de seguridad (prevención), observabilidad (detección) y puntos de control (recuperación).
Capa 1: Barandillas de seguridad (prevención)
Las barandillas son restricciones programáticas que el agente no puede romper.
Restricciones duras en código:
# No: confiar en instrucciones al agente
agent.run("Only modify files in the src/ directory")
# Sí: aplicar 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
)
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:
Al trabajar con APIs, usa esquemas para prevenir solicitudes malformadas. Aquí Apidog es clave. Define tu contrato una vez y el agente no podrá enviar datos incorrectos.
// 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 valida 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:
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)
Permite saber qué hace el agente sin supervisarlo en todo momento.
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)
with open(self.log_file, 'a') as f:
f.write(json.dumps(entry) + '\n')
def log_decision(self, decision: str, reasoning: str, confidence: float):
self.log("decision", {
"decision": decision,
"reasoning": reasoning,
"confidence": confidence
})
def log_action(self, action: str, params: dict, result: str):
self.log("action", {
"action": action,
"params": params,
"result": result[:200]
})
def log_error(self, error: str, context: dict):
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:
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)
Permiten pausas automáticas para revisión humana en momentos críticos.
Puntos de control automáticos:
from enum import Enum
from typing import Callable
from dataclasses import dataclass
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:
if trigger in self.auto_approve:
return True
checkpoint = Checkpoint(
trigger=trigger,
description=description,
data=data
)
self.pending.append(checkpoint)
return False
def approve(self, checkpoint_id: int) -> None:
if 0 <= checkpoint_id < len(self.pending):
self.pending.pop(checkpoint_id)
def reject(self, checkpoint_id: int) -> None:
raise RuntimeError(f"Checkpoint rejected: {self.pending[checkpoint_id]}")
# Uso en el agente
checkpoints = CheckpointManager(
auto_approve={CheckpointTrigger.BEFORE_FILE_WRITE}
)
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"]}
):
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 es enviar solicitudes malformadas. Apidog ayuda definiendo esquemas exactos que el agente debe cumplir.
Configuración de contratos de API:
- Importa o define tu especificación OpenAPI en Apidog
- Genera código cliente con validación integrada
- Proporciona al agente el cliente validado en lugar de acceso 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 no puede enviar datos inválidos porque el cliente valida antes de enviar la petición.
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 riesgosas, exige 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 el agente actúe 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 acciones del agente para que sean repetibles y seguras ante reintentos.
import hashlib
import os
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 instrucciones como restricciones. “No borres archivos” no es suficiente: usa permisos de archivo en su lugar.
- No tener plan de reversión. Usa git/copia de seguridad para revertir errores del agente.
- Ignorar puntuaciones de confianza. Baja confianza = pausa y revisión humana.
- Monitorización excesiva. Si supervisas cada paso, no tienes autonomía real.
- Especificación insuficiente del éxito. Define cuándo el agente debe detenerse, por ejemplo, “corrige el error y todas las pruebas pasan”.
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 buscar “autónomos con barandillas de seguridad”: obtienes el 80% del ahorro de tiempo con solo el 10% del riesgo.
Casos de uso en el mundo real
Migración de bases de código: Un equipo migró 200 endpoints de REST a GraphQL usando un agente autónomo. Las barandillas evitaron cambios en el esquema y los puntos de control requirieron aprobación antes de eliminar endpoints. Migración en 3 días en vez de 3 semanas, sin incidentes.
Generación de documentación: Un agente genera documentación de API a partir del código. Barandillas permiten solo leer ciertos directorios. Puntos de control pausan antes de publicar. El equipo revisa semanalmente en vez de escribir documentación manual.
Cobertura de pruebas: Un agente analiza el código y crea pruebas faltantes. Restricciones de presupuesto evitan exceso. Umbrales de confianza marcan pruebas inciertas para revisión humana. Cobertura subió de 60% a 85% en un mes.
Conclusión
Esto es lo que has aprendido:
- Los agentes de IA fallan de formas predecibles: desviación del alcance, abstracciones incorrectas, fallos en cascada, agotamiento de recursos
- Tres capas resuelven la mayoría de problemas: barandillas de seguridad (prevención), observabilidad (detección), puntos de control (recuperación)
- Las barandillas son código, no instrucciones: aplica restricciones programáticas
- Observabilidad = logs y métricas estructuradas, no observación manual
- Los puntos de control permiten verificación humana selectiva
- Los esquemas de API de Apidog convierten tu capa de API en una barandilla eficaz
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 monitorear la ejecución
- Crea puntos de control para operaciones de alto riesgo
- Deja ejecutar 30 minutos y revisa los logs
El objetivo no es eliminar a los humanos del ciclo, sino ubicarlos en el punto correcto: tomando decisiones de alto nivel, no corrigiendo errores triviales.
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 instrucciones. Un agente toma un objetivo, planifica y ejecuta pasos autónomamente. Los asistentes requieren intervención en cada ciclo; los agentes se ejecutan hasta terminar o alcanzar un punto de control.
¿Cómo saber si mi agente está listo para operar de forma autónoma?
Ejecuta en modo supervisado durante 10 sesiones. Si las intervenciones bajan a menos de 2 por sesión y son menores (aclaraciones, no correcciones), está listo. Si son frecuentes o requieren revertir, añade más barandillas.
¿Cuál es el mayor riesgo de los agentes autónomos?
Los fallos en cascada no detectados. Un pequeño error inicial puede escalar y el agente seguirá porque cada paso parece razonable. Los puntos de control cortan estas cascadas.
¿Estos patrones funcionan con cualquier LLM?
Sí. Barandillas de seguridad, observabilidad y puntos de control son independientes del modelo (Claude, GPT-4, Gemini, etc). Sólo varía la implementación.
¿La observabilidad ralentiza al agente?
Prácticamente nada. Escribir logs es casi inmediato. Los puntos de control dependen de la velocidad de la revisión humana.
¿Qué pasa si el agente toma una decisión errónea?
Por eso existen los puntos de control: rechaza y el agente revierte o intenta otro enfoque. Mejor aún: agrega tus preferencias a las instrucciones para que el agente aprenda con el tiempo.
¿Empezar con agentes supervisados o autónomos?
Siempre empieza supervisado. Puntos de control en cada acción importante hasta confiar en el agente. Luego retira puntos de control gradualmente para acciones de bajo riesgo.
¿Cómo ayuda Apidog con los agentes de IA?
Apidog genera clientes de API validados desde tus esquemas. El agente, usando estos clientes, no puede enviar solicitudes malformadas: toda una clase de errores queda prevenida antes de llegar a tu backend.
Top comments (0)