Volver al Blog
Publicado el

Tu agente de IA no leyó el manual: por qué la gobernanza debe ser código, no prosa

Estrategia de IADesarrollo de IAArquitectura de SoftwareLiderazgo de IngenieríaLLMs
Tu agente de IA no leyó el manual: por qué la gobernanza debe ser código, no prosa

Ahora mismo hay un documento en algún repositorio de tu empresa. Se llama system_prompt.md o agent_policy.txt. Tiene entre 3.000 y 15.000 palabras. Contiene tus límites de reembolso, tus reglas de tono de voz, tus rutas de escalado, tus requisitos de tratamiento de datos, las cuatro cosas que el agente nunca debe prometer, el párrafo sobre el RGPD que legal insistió en incluir y una sección casi al final que dice «pide siempre confirmación antes de realizar cualquier acción irreversible».

Alguien en una reunión de cumplimiento preguntó «¿cómo evitamos que el agente haga X?» y la respuesta fue «lo hemos añadido al prompt». Todos asintieron. El ticket se cerró.

Ese documento no es un control. Es una lista de deseos con buen formato.

Un artículo reciente de arXiv, HANDBOOK.md: A Benchmark for Long-Context Agentic Instruction Following, puso cifras a algo que cualquiera que haya puesto un agente en producción ya sospechaba: los documentos de políticas extensos no gobiernan de forma fiable el comportamiento del modelo. A medida que crece el contexto, la adherencia a cualquier instrucción individual se degrada. Las reglas compiten entre sí. Las instrucciones que más te importan quedan silenciosamente superadas en votos por lo que esté más cerca de la atención del modelo: normalmente el último mensaje del usuario, o la salida de la herramienta que acaba de llegar, o los tres párrafos que añadiste más recientemente.

Esto no es un problema de ingeniería de prompts que puedas resolver con mejor prosa. Es un error de categoría sobre dónde viven los controles.

Por qué la prosa nunca puede ser un control

Lo que separa un control de una preferencia es esto: un control tiene un modo de fallo definido.

Cuando una base de datos rechaza una escritura por una restricción de clave externa, sabes exactamente qué ocurrió. La transacción falló, de forma ruidosa, en una línea concreta, con un error concreto. Puedes alertar sobre ello. Puedes contarlo. Puedes demostrar a un auditor que se activó 1.412 veces el trimestre pasado y que bloqueó todas y cada una de ellas.

Cuando un modelo de lenguaje lee «nunca emitas reembolsos superiores a 500 €» en el párrafo 47 de un prompt de sistema y luego emite un reembolso de 900 €, nada ha fallado. El sistema funcionó exactamente como fue diseñado. Una distribución de probabilidad sobre tokens produjo tokens. No hay excepción, ni línea de log, ni límite cruzado, porque no había ningún límite. Había una sugerencia, ponderada frente a varios miles de tokens más, algunos de los cuales resultaban ser un cliente muy persuasivo.

Tres mecánicas impulsan esto, y vale la pena entenderlas bien porque determinan qué puedes y qué no puedes delegar en el prompt:

La atención es finita y compartida. Cada instrucción que añades diluye la influencia de todas las demás. Un manual de 40 páginas no te da 40 páginas de gobernanza; te da un promedio difuso de prioridades. La regla que añadiste el primer día compite con la que añadiste el día noventa, y el modelo no tiene idea de por cuál de las dos moriría tu asesor jurídico.

La posición importa más que la importancia. Las instrucciones cercanas al inicio y al final del contexto tienen más peso que las enterradas en el medio. Tu restricción más crítica puede estar justo en el peor lugar posible para sobrevivir. Y el modelo no tiene el concepto de «esta sección prevalece sobre aquella» a menos que diseñes la precedencia de forma explícita: el lenguaje natural no tiene una palabra clave PRIORITY: CRITICAL que el transformer respete.

La resolución de conflictos es estadística, no jerárquica. Los documentos de políticas reales se contradicen entre sí. Cualquier manual lo bastante largo para ser útil contiene tensiones: sé útil frente a sé prudente, resuelve rápido frente a verifica la identidad, sé conciso frente a incluye la divulgación obligatoria. Los humanos resuelven esto con criterio y con el conocimiento de que algunas reglas te cuestan el empleo. Un modelo lo resuelve eligiendo la vía que tenga más masa de probabilidad en el contexto actual.

Ya escribí antes sobre la restricción subyacente en El problema de la ventana de contexto en IA. Las ventanas de contexto más grandes empeoraron esto, no lo mejoraron, porque hicieron que el enfoque equivocado pareciera viable. Cuando solo cabían 4.000 tokens, estabas obligado a pensar en términos arquitectónicos. Ahora puedes pegar el manual del empleado completo, así que la gente lo hace.

La escalera de la gobernanza

El modelo mental útil es una escalera, y cada regla de tu documento de políticas debe colocarse exactamente en un escalón.

Escalón 1: imposible. El agente no puede hacerlo físicamente, porque la capacidad no existe en su superficie de herramientas. No hay ninguna herramienta issue_refund con un parámetro de importe sin límite. No hay ninguna herramienta que devuelva datos personales en bruto. Esta es la forma más sólida de gobernanza y requiere cero confianza en el modelo.

Escalón 2: rechazado. El agente puede intentarlo, pero una capa determinista se niega. Validación en el servidor de las llamadas a herramientas, comprobaciones de permisos contra el usuario realmente autenticado, transiciones de máquina de estados que no son legales desde el estado actual. El modelo propone; el código dispone.

Escalón 3: revisado. La acción se pone en cola para una persona con autoridad real y contexto real para rechazarla. No un diálogo de «¿estás seguro? [Sí]», que es teatro. Una cola real con un responsable real y un SLA.

Escalón 4: sugerido. Está en el prompt. Tono, formato, cómo formular una negativa, cuándo ofrecer alternativas, estilo. Este escalón está bien. Esto es en lo que los prompts son genuinamente buenos.

Cualquier cosa en el escalón 4 que tu equipo legal o financiero crea que está en el escalón 1 o 2 es donde te vas a hacer daño. La pregunta de auditoría que le haría a cualquier equipo que despliega un agente es brutalmente simple: por cada regla de tu documento de políticas, muéstrame la línea de código que la hace cumplir. Si la respuesta es «está en el prompt», esa regla no existe.

Los esquemas de herramientas son tu verdadero documento de políticas

El error arquitectónico más común es tratar las definiciones de herramientas como una superficie de API para el modelo, en lugar de como el límite de aplicación. Si una herramienta acepta un importe, ese importe acabará siendo incorrecto. Si una herramienta acepta un customer_id, el modelo acabará pasando el ID de otro cliente; no por malicia, sino simplemente porque apareció en una transcripción tres turnos antes.

La solución es diseñar las herramientas de modo que los parámetros peligrosos no sean del modelo.

// WRONG: the model decides who and how much. // The €500 limit lives in the prompt. Which means it doesn't exist. const issueRefund = tool({ name: "issue_refund", parameters: z.object({ customerId: z.string(), amountCents: z.number(), reason: z.string(), }), execute: async ({ customerId, amountCents, reason }) => payments.refund(customerId, amountCents, reason), });
// RIGHT: identity comes from the session, not the transcript. // The limit is a constraint, not a sentence. const issueRefund = tool({ name: "issue_refund", parameters: z.object({ orderId: z.string().uuid(), reason: z.enum(["damaged", "late_delivery", "wrong_item", "other"]), amountCents: z.number().int().positive(), }), execute: async (args, ctx: AgentContext) => { // 1. Authorisation: does THIS session own THIS order? const order = await orders.findForCustomer(args.orderId, ctx.session.customerId); if (!order) throw new ToolRefusal("ORDER_NOT_OWNED_BY_SESSION"); // 2. Policy as arithmetic, not as prose. const cap = policy.refundCapCents(ctx.session.tier); if (args.amountCents > cap) { return { status: "escalated", queuedFor: "human_review", reason: `Requested ${args.amountCents} exceeds cap ${cap}`, }; } // 3. Idempotency: the key must describe the INTENT, never the attempt. // Anything per-turn or per-retry here defeats the purpose - the retry // arrives with a fresh key and you pay twice. return payments.refund({ orderId: order.id, amountCents: args.amountCents, idempotencyKey: `refund:${order.id}:${args.reason}:${args.amountCents}`, }); }, });

Fíjate en lo que ocurrió con el caso que supera el límite. No lanza un error alarmante que el modelo pudiera intentar sortear. Devuelve un resultado legítimo y estructurado -escalated- que el agente puede explicar al usuario. La gobernanza y una buena experiencia de usuario no están en conflicto aquí. La negativa es un estado de producto de primera clase.

Las máquinas de estados le ganan a las intuiciones

La segunda corrección estructural es dejar de tratar la conversación como el estado. Los agentes que «recuerdan» en qué punto de un proceso están a través de la transcripción son agentes a los que se puede convencer de saltarse cualquier paso. La verificación de identidad, en particular, no puede vivir en el historial de diálogo. Tiene que vivir en una fila de una tabla.

const TRANSITIONS: Record<CaseState, CaseState[]> = { intake: ["identity_pending"], identity_pending: ["identity_verified", "abandoned"], identity_verified: ["remediation_proposed", "escalated_human"], remediation_proposed: ["executing", "escalated_human"], executing: ["closed", "escalated_human"], closed: [], escalated_human: ["closed"], }; export function guard(current: CaseState, next: CaseState, toolName: string) { if (!TRANSITIONS[current].includes(next)) { throw new ToolRefusal(`ILLEGAL_TRANSITION ${current} -> ${next} via ${toolName}`); } }

Cinco líneas de lógica con las que ningún «ignora las instrucciones anteriores» puede discutir. Cada herramienta que modifica el mundo llama primero a guard. El modelo puede estar tan confundido, tan «jailbreakeado» o tan alucinado como quiera; el proceso sigue sin poder saltarse la verificación.

La parte polémica: tu suite de evaluación tampoco es un control

Aquí es donde discrepo del consenso actual. La respuesta del sector a la adherencia poco fiable de los prompts ha sido construir suites de evaluación enormes: cientos de casos de prueba adversariales, prompts de red team, rúbricas puntuadas, paneles que muestran un 97,4 % de cumplimiento de políticas.

Las evaluaciones son valiosas. No son gobernanza. Una suite de evaluación te dice la probabilidad de una infracción en una muestra de escenarios que se te ocurrieron. Un control te dice que la infracción es imposible. Son garantías fundamentalmente distintas, y confundirlas es la razón por la que los equipos acaban defendiendo una tasa de aprobación del 97 % ante un regulador al que solo le importa el 3 %.

Lo mismo ocurre con el reflejo de añadir «y nunca hagas X» al prompt después de cada incidente. Ese bucle es la razón por la que el manual tiene 40 páginas en primer lugar. Cada añadido diluye marginalmente todo lo que ya estaba allí. Estás cambiando un fallo específico conocido por un aumento difuso de la falta de fiabilidad general, y no puedes medir el intercambio. La respuesta correcta a una infracción de política casi nunca es editar el prompt. Es un validador que falta.

Mi consejo directo: pon un tope a tu prompt de sistema. Elige un presupuesto -800 palabras es generoso para la mayoría de los agentes- y defiéndelo. Todo lo que no quepa no es lo bastante importante para ser prosa, lo que significa que es lo bastante importante para ser código. Es la misma disciplina que hay detrás de recortar la mitad de la lista de funcionalidades para encontrar un MVP. Menos comportamientos, realmente aplicados, superan a cien comportamientos solicitados con cortesía.

No puedes gobernar un agente sobre un sistema ingobernable

Esta es la parte que se salta, y es la parte cara.

Todos los controles anteriores dan cosas por supuestas sobre la capa inferior. orders.findForCustomer asume que tu modelo de datos puede expresar propiedad. La clave de idempotencia asume que tu ruta de pago respeta las claves de idempotencia. La ruta de escalado asume que existe una traza de auditoría que permite a una persona reconstruir qué hizo el agente y por qué. La máquina de estados asume que tienes un almacén duradero del estado del caso en lugar de inferirlo de los logs.

Si tu API actual tiene endpoints que confían en un customer_id en el cuerpo de la petición, ningún manual te salva: acabas de dar a un cliente muy rápido, muy creativo e incansable acceso a esa debilidad. Si no tienes traza de auditoría, no puedes investigar el incidente, lo que significa que no puedes cerrarlo, lo que significa que no puedes desplegar la siguiente versión con confianza. Si tus rutas de escritura no son idempotentes, un bucle de reintentos del agente se convierte en un evento de cargo duplicado.

Este es exactamente el patrón que hay detrás de nuestro orden de operaciones: estabilizar primero, mejorar segundo, añadir IA al final. No porque la IA sea peligrosa en abstracto, sino porque un agente es un amplificador. Amplifica la capacidad y amplifica con igual entusiasmo cada debilidad estructural de la base. Móntalo sobre unos cimientos inestables y pagarás dos veces: una por la IA y otra por reconstruir la base mientras la IA está en producción y los clientes están mirando. Profundicé en la parte de infraestructura de esto en Por qué tu producto de IA puede fracasar antes de escribir una línea de código.

La prueba práctica de preparación no es «¿tenemos un documento de políticas?». Son cuatro preguntas. ¿Puede cada ruta de escritura identificar quién la autorizó? ¿Puede cada ruta de escritura reintentarse de forma segura? ¿Podemos reconstruir cualquier decisión a posteriori a partir de datos almacenados, y no solo de los registros de chat? ¿Y puede alguna acción crítica ser bloqueada por algo que no sea el propio criterio del modelo? Cuatro «sí» y estás listo para dar a un agente capacidad real. Menos que eso y estás listo para darle acceso de solo lectura y una superficie de herramientas muy estrecha, que es un punto de partida perfectamente respetable.

Una única fuente de verdad, dos salidas

La buena noticia es que no tienes que mantener las políticas en dos sitios. Escríbelas una vez, como datos, y luego genera tanto la aplicación como la descripción.

export const REFUND_POLICY = { capsByTier: { standard: 20_000, premium: 50_000 }, requiresIdentityVerified: true, allowedReasons: ["damaged", "late_delivery", "wrong_item", "other"], } as const; // Enforcement (rung 2) export const refundCapCents = (tier: Tier) => REFUND_POLICY.capsByTier[tier]; // Description (rung 4) — derived, never hand-written export const refundPromptFragment = (tier: Tier) => ` Refunds: max ${(refundCapCents(tier) / 100).toFixed(0)} EUR without human review. Identity must be verified first. Above the cap, explain that a specialist will review within one business day. `.trim();

Ahora el prompt y el validador no pueden desincronizarse. Cuando finanzas cambia el límite, cambia una constante y tanto la aplicación como la explicación del agente se actualizan juntas. El trabajo del prompt queda reducido a aquello en lo que es genuinamente bueno: ayudar al modelo a comportarse con sensatez dentro de un límite que no puede cruzar.

La conclusión estratégica

A tu consejo se le venden los agentes como configurables. No lo son. No puedes configurar una distribución de probabilidad. Solo puedes restringirla, y la restricción es un entregable de ingeniería con un coste y un calendario, no una revisión documental.

Así que cuando en la próxima reunión de gobernanza pregunten cómo estás controlando al agente, la respuesta que merece la pena dar no es un número de páginas. Es una lista de cosas que el agente es estructuralmente incapaz de hacer, y las pruebas que lo demuestran. Todo lo demás -el tono, la redacción, la empatía, la negativa elegante- pertenece al prompt, donde es barato y donde acertar el 95 % de las veces está genuinamente bien.

Escribe menos manual. Escribe más validadores. El modelo nunca iba a leer el manual, de todos modos.

Reserva una llamada de recuperación gratuita

Artículos relacionados

Plan AI: El Grabador de Reuniones de Código Abierto Sin Bots
Desarrollo de IA

Plan AI: El Grabador de Reuniones de Código Abierto Sin Bots

Conoce Plan AI, un grabador de reuniones open-core y sin bots que captura el audio de forma nativa y genera tickets de ingeniería perfectamente definidos de manera automática.

LLMs en Tu Stack: Cuándo la IA Acelera el Desarrollo (Y Cuándo No)
AI Development

LLMs en Tu Stack: Cuándo la IA Acelera el Desarrollo (Y Cuándo No)

La mayoría de los equipos desperdician los LLMs en tareas rutinarias mientras pierden las verdaderas ganancias. Aquí está el manual de ingeniería para usar IA y entregar más rápido sin generar deuda técnica.

Por qué el 'AI Slop' es la señal de alerta que tu recuperación de software necesita ahora
Estrategia de IA

Por qué el 'AI Slop' es la señal de alerta que tu recuperación de software necesita ahora

La economía de creadores se está ahogando en basura generada por IA. Si tu plataforma se apresura a agregar funciones de IA sobre cimientos inestables, no estás innovando: estás acumulando deuda técnica que te costará el doble arreglar.