Allowlist vs Blocklist para agentes de IA: por qué default deny es más seguro

Enfoque práctico para el acceso a herramientas en producción: allowlist con default deny, incident blocklist, stop reasons y audit logs.
En esta página
  1. Idea en 30 segundos
  2. Problema
  3. Solución
  4. Allowlist ≠ Blocklist
  5. Métricas de control de acceso a tools
  6. Cómo se ve en la arquitectura
  7. Ejemplo
  8. En código se ve así
  9. Cómo se ve durante la ejecución
  10. Errores típicos
  11. Autoevaluación
  12. FAQ
  13. Dónde encaja en el sistema general
  14. Páginas relacionadas

Idea en 30 segundos

Allowlist en runtime define qué tools puede invocar el agente. Blocklist solo prohíbe una parte de tools dentro de un conjunto ya grande.

Cuándo se necesita: cuando un agente tiene acceso a APIs reales, acciones de escritura o recibe tools nuevos con frecuencia en producción.

Problema

Muchos equipos empiezan con blocklist: “prohibimos las herramientas peligrosas”. Al principio parece rápido y cómodo. En producción, este modelo se rompe pronto.

La razón es simple: cada tool nuevo queda disponible automáticamente si no se bloquea explícitamente. Es decir, el acceso crece por defecto, no por una decisión explícita.

Analogía: es como una oficina sin lista de puertas permitidas, pero con una lista de “no entrar aquí”. En cuanto aparece una sala nueva, queda abierta para todos hasta que alguien recuerde bloquearla.

Solución

La solución es definir default deny en el policy layer y permitir tools solo mediante allowlist. La blocklist queda como freno de emergencia adicional para modo incidente, no como modelo principal de acceso.

El policy layer devuelve una decisión técnica por cada llamada: allow, deny o approval_required. Esta decisión se toma en cada paso, no solo al final del run. Es una capa separada del sistema, no parte del prompt ni de la lógica del modelo.

Allowlist ≠ Blocklist

Son enfoques de control distintos:

  • Allowlist: solo está permitido lo que se agrega explícitamente a la policy.
  • Blocklist: todo está permitido, excepto lo que se prohíbe explícitamente.

Uno sin el otro no es suficiente:

  • sin allowlist, los accesos se expanden entre releases casi sin notarlo
  • sin blocklist, es más difícil desactivar de emergencia un tool concreto durante un incidente

Ejemplo:

  • allowlist: search.read, kb.read, refund.lookup
  • incident blocklist: negar temporalmente browser.run por un vendor inestable

Métricas de control de acceso a tools

Estas métricas y señales trabajan juntas en cada paso del agente.

MétricaQué controlaMecánicas clavePara qué
Default denyRegla base de accesodefault = deny
deny by default
Un tool nuevo no queda disponible automáticamente
AllowlistQué tools están permitidosnombres explícitos de tools
capability scoping
Define límites explícitos para la ejecución en runtime
Incident blocklistBloqueos temporales de emergenciaincident mode deny list
time-bound rules
Permite reducir riesgo rápido sin release
Write escalationAcciones de escritura riesgosasapproval_required
separate write policy
Evita acciones irreversibles sin control
Policy observabilityVisibilidad de decisiones de policyaudit logs
alerts on deny spikes
No limita acciones de forma directa, pero muestra dónde y por qué se bloquea el acceso

Cómo se ve en la arquitectura

El policy layer (tool gateway) se ubica entre runtime y tools, y es el único punto de control de acceso antes de cada paso. Cada decisión (allow, deny, approval_required) se registra en el audit log.

Cada paso del agente pasa por este flow antes de ejecutarse: runtime no ejecuta la acción directamente, primero hay verificación de policy y después ejecución. Para acciones de escritura, la policy puede devolver approval_required; ese es un flow de confirmación separado que no se muestra en este diagrama (ver Human approval).

Resumen del flow:

  • Runtime forma el tool call
  • Policy layer aplica default deny, luego allowlist e incident blocklist
  • allow -> se ejecuta el tool call
  • deny -> se devuelve un stop reason
  • cada decisión se escribe en audit log

En runtime, deny se convierte en un stop reason explícito visible en logs y en la respuesta del run.

Ejemplo

Un agente de soporte recibe una solicitud para cerrar tickets de forma masiva. El tool ticket.close_bulk no está en la allowlist, así que la llamada se bloquea de inmediato.

Durante un incidente separado, el equipo agrega browser.run a la incident blocklist. Aunque ese tool esté en la allowlist, el policy layer devuelve temporalmente deny("incident_deny").

La allowlist limita el acceso base y la blocklist aporta control rápido de emergencia.

En código se ve así

En el esquema simplificado de arriba se muestra el control flow principal. En la práctica, la verificación se ejecuta en un único lugar: policy layer antes de cada paso.

Ejemplo de configuración de allowlist:

YAML
policy:
  default: deny
  allowlist:
    - search.read
    - kb.read
    - refund.lookup
incident_blocklist:
  - browser.run
PYTHON
decision = policy.evaluate(tool, user_context, mode="normal")

if decision.outcome == "approval_required":
    if not approval.ok():
        audit.log(run_id, decision.outcome, reason=decision.reason, tool=tool)
        return stop(decision.reason)
    else:
        audit.log(run_id, "approval_granted", reason="human_approved", tool=tool)

elif decision.outcome == "deny":
    audit.log(run_id, decision.outcome, reason=decision.reason, tool=tool)
    alerts.notify_if_needed(run_id, decision.reason, tool=tool)
    return deny(decision.reason)

result = tool.execute(args)
decision = Decision.allow(reason="policy_ok")
audit.log(run_id, decision.outcome, reason=decision.reason, tool=tool, result=result.status)
return result

Cómo se ve durante la ejecución

TEXT
Escenario 1: tool fuera de allowlist (deny)

1. Runtime forma una llamada a ticket.close_bulk.
2. Policy layer verifica la allowlist.
3. Decisión: deny (tool_not_allowed).
4. Audit: decision=deny, tool=ticket.close_bulk, reason=tool_not_allowed.
5. La acción no se ejecuta.

---

Escenario 2: bloqueo por incidente (incident_deny)

1. Runtime forma una llamada a browser.run.
2. El tool está en allowlist, pero el modo incidente está activo.
3. Policy layer verifica la blocklist y devuelve deny (incident_deny).
4. Audit: decision=deny, tool=browser.run, reason=incident_deny.
5. El run se detiene sin llamar al tool.

---

Escenario 3: llamada permitida (allow)

1. Runtime forma una llamada a kb.read.
2. Policy layer verifica reglas: allow.
3. El tool se ejecuta.
4. Audit: decision=allow, tool=kb.read, result=ok.
5. El resultado vuelve al runtime.

Errores típicos

  • usar blocklist como modelo principal de acceso
  • no usar default deny para tools nuevos
  • permitir wildcards como * sin límites estrechos
  • mantener tools “universales” como workflow.run_anything
  • loguear solo allow y no deny/approval_required
  • verificar acceso en prompt o UI en lugar de policy layer

Como resultado, el acceso parece controlado, pero en realidad se expande en cada release.

Autoevaluación

Chequeo rápido de policy allowlist antes de lanzar a producción:

Progreso: 0/8

⚠ Faltan controles base de governance

Antes de production necesitas como mínimo control de acceso, límites, audit logs y parada de emergencia.

FAQ

P: ¿Se puede operar producción solo con blocklist?
R: Para producción, no. Blocklist sirve como mecanismo de emergencia, pero el modelo base debe ser default deny + allowlist.

P: ¿Cómo empezar con allowlist?
R: Empieza con un conjunto mínimo de tools read-only. Agrega acciones de escritura por separado, con condiciones explícitas y approval.

P: ¿Una allowlist wildcard (crm.*) está bien?
R: Solo en casos acotados y con revisión regular. Si no, el wildcard se convierte rápido en default-allow oculto. Por ejemplo, crm.* permitirá crm.delete_all_contacts si ese tool aparece en el siguiente release.

P: ¿Dónde implementar estas verificaciones?
R: En un policy layer centralizado (tool gateway), no en el prompt ni en la lógica de UI.

P: ¿Qué hacer si hay que desactivar un tool con urgencia?
R: Añádelo a la incident blocklist, registra la razón en audit log y luego vuelve a la policy allowlist permanente.

Dónde encaja en el sistema general

Allowlist/blocklist es una de las capas de Agent Governance. Junto con RBAC, presupuestos, approval y audit forma un sistema unificado de control de ejecución.

Páginas relacionadas

Siguiente sobre este tema:

⏱️ 7 min de lecturaActualizado 25 de marzo de 2026Dificultad: ★★★
Implementar en OnceOnly
Budgets + permissions you can enforce at the boundary.
Usar en OnceOnly
# onceonly guardrails (concept)
version: 1
budgets:
  max_steps: 25
  max_tool_calls: 12
  max_seconds: 60
  max_usd: 1.00
policy:
  tool_allowlist:
    - search.read
    - http.get
writes:
  require_approval: true
  idempotency: true
controls:
  kill_switch: { enabled: true }
Integrado: control en producciónOnceOnly
Guardrails para agentes con tool-calling
Lleva este patrón a producción con gobernanza:
  • Presupuestos (pasos / topes de gasto)
  • Permisos de herramientas (allowlist / blocklist)
  • Kill switch y parada por incidente
  • Idempotencia y dedupe
  • Audit logs y trazabilidad
Mención integrada: OnceOnly es una capa de control para sistemas de agentes en producción.

Autor

Nick — ingeniero que construye infraestructura para agentes de IA en producción.

Enfoque: patrones de agentes, modos de fallo, control del runtime y fiabilidad del sistema.

🔗 GitHub: https://github.com/mykolademyanov


Nota editorial

Esta documentación está asistida por IA, con responsabilidad editorial humana sobre la exactitud, la claridad y la relevancia en producción.

El contenido se basa en fallos reales, post-mortems e incidentes operativos en sistemas de agentes de IA desplegados.