Anti-pattern Write Access by Default: acceso write por defecto

Anti-pattern donde el agente tiene acceso write sin restricciones.
En esta página
  1. Idea en 30 segundos
  2. Ejemplo del anti-pattern
  3. Por qué aparece y qué sale mal
  4. Enfoque correcto
  5. Prueba rápida
  6. Cómo se diferencia de otros anti-patterns
  7. Blind Tool Trust vs Write Access by Default
  8. Agents Without Guardrails vs Write Access by Default
  9. Tool Calling for Everything vs Write Access by Default
  10. Autoevaluación: ¿tienes este anti-pattern?
  11. FAQ
  12. Qué sigue

Idea en 30 segundos

Write Access by Default es un anti-pattern donde el agente recibe write-tools por defecto, sin policy-gate ni verificación antes de ejecutar.

Como resultado, un error del modelo o una ruta incorrecta no se convierte solo en respuesta errónea, sino en cambio real del estado externo.

Regla simple: write no debe ser "por defecto". Debe pasar por una ruta separada y controlada con verificación explícita de permisos, contexto y condiciones de ejecución.


Ejemplo del anti-pattern

El equipo construye un agente de soporte que lee estado de pedido y, si hace falta, puede cerrar un ticket o enviar un correo.

El agente recibe write-tools de inmediato, sin etapa dedicada de control antes de actuar.

PYTHON
decision = agent.decide_next_action(user_message)
# la ruta es incorrecta, pero write sigue habilitado
result = run_tool(decision.tool, decision.args)
return result

En este esquema falta protección base:

PYTHON
# no hay deny-by-default para write-tools
# no hay approval_required para acciones riesgosas
# no hay idempotency_key para retries
# no hay tenant/env scope estricto

Para este caso se necesita un policy-gate antes de cualquier paso write:

PYTHON
if decision.tool in WRITE_TOOLS and not is_write_allowed(ctx, decision):
    return stop("approval_required")

Si no se cumplen condiciones, el run no debe pasar a una acción write externa.

En este caso, Write Access by Default agrega:

  • riesgo de cambios no deseados en sistemas externos
  • operaciones write duplicadas durante retries
  • mayor blast radius en entornos multi-tenant

Por qué aparece y qué sale mal

Este anti-pattern aparece cuando el equipo quiere que el agente sea "lo más autónomo posible" y abre acceso write antes de construir límites de control.

Causas típicas:

  • enfoque demo-first: primero dar todas las herramientas, luego agregar restricciones
  • ausencia de separación explícita entre rutas read y write
  • reglas de acceso descritas en prompt, no forzadas en gateway
  • falta de idempotency_key obligatorio para write-operaciones

Como resultado aparecen problemas:

  • side effects inseguros (cambios de estado) - el agente puede escribir donde debía solo leer
  • acciones repetidas - retry o loop repite la misma write-operación
  • blast radius alto - sin scope estricto, el error impacta tenant/env incorrecto
  • análisis de incidente difícil - cuesta demostrar por qué write fue permitido
  • pérdida de previsibilidad - el equipo no controla cuándo el sistema pasa a write

A diferencia de Blind Tool Trust, aquí el problema central no es validar payload, sino que write está abierto por defecto.

Señales típicas de producción de control write débil:

  • write-tools se llaman incluso en escenarios que deberían ser read-only
  • en logs hay muchos write-calls con el mismo args_hash o sin idempotency_key
  • approval_required casi no aparece aunque el porcentaje de write sea alto
  • blocked write attempts casi no ocurren aunque el sistema proponga risky actions de forma regular
  • audit-logs no muestran qué regla policy permitió write
  • el equipo no puede explicar claramente por qué un write concreto fue permitido en ese run
  • los errores se detectan después de la acción externa, no en policy-gate

Es importante: cada write-call cambia estado externo y muchas veces no tiene rollback simple. Sin deny-by-default y ruta write controlada, una inference fallida se vuelve incidente de producción.

Enfoque correcto

Empieza con modelo read-first: los read-tools quedan disponibles por ruta, y los pasos write pasan por verificación separada vía policy-gate.

Marco práctico:

  • aplica deny-by-default para todos los write-tools
  • separa rutas read_only y write_candidate
  • exige approval para write-acciones riesgosas
  • toma tenant_id y env solo desde contexto autenticado, no desde model output
  • agrega idempotency_key en cada write-operación
  • loggea stop_reason y decisiones del policy-gate en cada write-step
PYTHON
WRITE_TOOLS = {"ticket.close", "refund.create", "email.send"}


def execute_action(user_message: str, ctx: dict):
    decision = agent.next_action(user_message)

    if decision.tool in WRITE_TOOLS:
        if not is_write_allowed(ctx, decision):  # policy gate: role, route allowlist, tenant/env scope
            return stop("approval_required")

        scoped_args = enforce_scope(
            decision.args,
            tenant_id=ctx["tenant_id"],
            env=ctx["env"],
        )
        scoped_args["idempotency_key"] = make_idempotency_key(ctx["run_id"], decision)
        return run_tool(decision.tool, scoped_args)

    return run_tool(decision.tool, decision.args)  # read-only tool from allowed set

En este esquema, el paso write queda controlado: el sistema ejecuta de forma segura o detiene el run de manera transparente.

Prueba rápida

Si respondes "sí" a estas preguntas, tienes riesgo del anti-pattern Write Access by Default:

  • ¿Un write-tool puede llamarse sin verificación explícita de policy/approval?
  • ¿Un retry a veces repite la misma write-acción sin idempotency_key?
  • ¿El equipo no puede explicar rápidamente por qué un write concreto fue permitido?

Cómo se diferencia de otros anti-patterns

Blind Tool Trust vs Write Access by Default

Blind Tool TrustWrite Access by Default
Problema principal: tool output se acepta sin validación.Problema principal: acceso write abierto por defecto.
Cuándo aparece: cuando faltan checks parse/schema/invariant antes de decidir.Cuándo aparece: cuando write no pasa por deny-by-default ni approval-gate.

En resumen: Blind Tool Trust trata de calidad de datos antes de actuar, mientras Write Access by Default trata de permisos para la acción.

Agents Without Guardrails vs Write Access by Default

Agents Without GuardrailsWrite Access by Default
Problema principal: faltan límites runtime y control policy en general.Problema principal: específicamente las write-operaciones no tienen contorno de acceso estricto.
Cuándo aparece: cuando el sistema no tiene safety-policy clara para execution.Cuándo aparece: cuando write se permite como ruta estándar en vez de excepción vía policy-gate.

En resumen: Agents Without Guardrails es un problema más amplio de límites de ejecución, y Write Access by Default es específicamente un modelo de acceso write inseguro.

Tool Calling for Everything vs Write Access by Default

Tool Calling for EverythingWrite Access by Default
Problema principal: se llaman tools de más, incluso cuando no hacen falta.Problema principal: una vez hay tool-call, write puede pasar sin control suficiente.
Cuándo aparece: cuando no hay ruta no_tool estable para casos simples.Cuándo aparece: cuando el sistema no separa niveles de acceso read y write.

En resumen: Tool Calling for Everything aumenta cantidad de llamadas, y Write Access by Default aumenta el costo del error de cada write-call.

Autoevaluación: ¿tienes este anti-pattern?

Chequeo rápido del anti-pattern Write Access by Default.
Marca los puntos para tu sistema y revisa el estado abajo.

Revisa tu sistema:

Progreso: 0/8

⚠ Hay señales de este anti-patrón

Intenta mover los pasos simples a un workflow y dejar el agente solo para decisiones complejas.

FAQ

Q: ¿Esto significa que el agente nunca debe ejecutar write-acciones?
A: No. Las write-acciones son posibles, pero solo por ruta controlada: policy-gate, approval (cuando aplique), scope enforcement e idempotency.

Q: ¿Cuál es la diferencia entre policy-gate y approval?
A: Policy-gate es verificación determinista de reglas en runtime. Approval es confirmación separada para una acción riesgosa específica. Son capas de control distintas.

Q: ¿Qué mínimo implementar primero?
A: Empieza con deny-by-default para write, idempotency_key obligatorio, tenant/env scope estricto y logging de stop_reason para intentos write bloqueados.


Qué sigue

Anti-patterns relacionados:

Qué construir en su lugar:

⏱️ 8 min de lecturaActualizado 17 de marzo de 2026Dificultad: ★★★
Implementar en OnceOnly
Safe defaults for tool permissions + write gating.
Usar en OnceOnly
# onceonly guardrails (concept)
version: 1
tools:
  default_mode: read_only
  allowlist:
    - search.read
    - kb.read
    - http.get
writes:
  enabled: false
  require_approval: true
  idempotency: true
controls:
  kill_switch: { enabled: true, mode: disable_writes }
audit:
  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.