Una sola API key estática compartida entre toda una flota de agentes es una brecha que tarde o temprano va a pasar. Estos son los patrones que usamos para acotar, rotar y auditar credenciales, de modo que cuando un secreto se filtre, el daño sea mínimo.

En resumen
- En seguridad, un agente es básicamente un programa que decide en runtime qué hacer con tus credenciales, razonando sobre texto que no controlas del todo.
- El modelo nunca debería ver un secreto en crudo. Solo ve handles de herramientas; tu runtime resuelve la credencial fuera de la frontera del lenguaje.
- Apunta a credenciales débiles a propósito: de vida corta, acotadas y por agente. Las tres cosas a la vez, no una sola.
- Haz que rotar sea algo rutinario que el sistema ya espera, y registra cada lease (nunca el token) para que acotar un incidente tome minutos y no adivinanzas.
- Ajusta la ceremonia al radio de daño. Un script personal va con una env var; una flota que mueve dinero va con toda la maquinaria.
Desde el punto de vista de la seguridad, un agente de IA es un programa que decide en runtime qué hacer con tus credenciales. Ahí está el problema entero, en una sola frase. Cuando tenías un cron que llamaba a una sola API, podías dejar la key hardcodeada y olvidarte. Una flota de agentes es otra historia: muchos procesos, cada uno razonando sobre texto que no controlas del todo, cada uno capaz de llamar herramientas y soltar logs. Cuando termines de leer vas a tener un modelo concreto para que un secreto filtrado quede en algo pequeño, de vida corta, acotado, auditable, y una idea honesta de cuándo toda esta maquinaria realmente vale la pena.
El escenario que más me preocupa es ese en que la primera inyección de prompt o una línea de log perdida termina comprometiendo la cuenta completa. Por eso existe Infuse, nuestro gestor de secretos de API. Abajo te dejo los patrones que de verdad aguantan con una flota encima, más las concesiones de las que nadie habla.
01 · Por qué una flota rompe las reglas de siempre
Un solo script es un sistema cerrado. Lo escribiste tú, sabes a qué llama, y la única entrada no confiable es, a lo sumo, un payload de webhook que validas en la puerta. Puedes dejar la key hardcodeada, restringir los permisos del archivo y tener todo el flujo en la cabeza.
Un agente rompe cada una de esas suposiciones. El "camino de ejecución" lo decide en runtime un modelo razonando sobre texto, y parte de ese texto viene de afuera: una página extraída de la web, un correo, el resultado de una herramienta, un mensaje del usuario. Ese texto puede traer instrucciones. El agente no tiene una separación limpia entre datos y código como la tiene tu script; para un modelo de lenguaje, los datos son el código.
Ahora multiplica eso por una flota. Tienes un agente de investigación, uno de facturación, uno de operaciones, quizás un enjambre entero conectado entre sí. Cada uno toca secretos. Cada uno genera logs. A cada uno lo puedes desviar, aunque sea un poco, con lo que caiga en su ventana de contexto.
Importante
Da por sentado que toda credencial que un agente pueda alcanzar ya está filtrada, y diseña para que eso salga barato. La meta no es evitar cada filtración: es asegurarte de que ninguna te salga cara.
Si manejas los secretos de la flota como manejabas el cron, una key estática, compartida, eterna, estás a una sola instrucción inyectada con maña de que esa key haga todo lo que puede hacer, en cada sistema que alcance. El resto de este artículo va de achicar el tamaño de ese "todo" y de ese "cada sistema".
02 · Nunca metas una key en el prompt
Esta es la regla que se rompe primero, casi siempre sin querer. Alguien mete una API key en el system prompt para que el agente "tenga lo que necesita". Parece inofensivo. No lo es. Ese secreto ahora vive en:
- Los logs de requests del proveedor del modelo.
- Tu propio historial de conversación, que casi siempre termina en una base de datos.
- Cualquier herramienta de trazas u observabilidad que tengas conectada.
- La ventana de contexto misma, donde una instrucción inyectada con maña puede pedirle al modelo que la repita tal cual.
El arreglo es estructural, no un recordatorio. Un recordatorio ("no metas keys en los prompts") falla en el momento en que alguien anda apurado. La estructura significa que el agente no puede ver una credencial en crudo, porque ninguna llega nunca a su contexto.
La frontera del handle de herramienta
El agente ve handles de herramientas: schemas sin ningún secreto adentro. Cuando decide llamar a la API de pagos, emite un tool call. Tu runtime, fuera del modelo, resuelve la credencial y hace el request. El modelo recibe el resultado, nunca la key.
// El modelo ve esta herramienta. No tiene ningún secreto dentro.
const sendInvoice = {
name: "send_invoice",
description: "Envía una factura a un cliente por id",
input_schema: {
type: "object",
properties: { customerId: { type: "string" }, amountCents: { type: "integer" } },
required: ["customerId", "amountCents"],
},
}
// El secreto se resuelve aquí, en TU código, después de que el modelo lo pide.
async function runSendInvoice(args, ctx) {
const cred = await vault.lease({
agent: ctx.agentId,
scope: "billing:invoice.write",
ttlSeconds: 300,
})
return billingClient.sendInvoice(args, cred.token)
}
El modelo produjo la intención. Tu código produjo el efecto. La credencial nunca cruzó la frontera del lenguaje, así que ninguna inyección de prompt puede sacar algo que el modelo nunca tuvo. Este es el cambio con mayor retorno que puedes hacer, y casi no cuesta nada una vez que tu capa de herramientas es el lugar donde viven las credenciales.
03 · De vida corta, acotada, por agente
Una key estática carga poder ilimitado hasta que alguien se entera de que se filtró. Reemplázala por credenciales débiles a propósito: tres propiedades que solo sirven de verdad cuando van juntas.
- De vida corta. Saca un lease por lo que dura una sola tarea, medido en minutos. Para cuando alguien pudiera aprovechar un token de cinco minutos filtrado, ya no le sirve de nada.
- Acotada. El token del snippet de arriba puede escribir un tipo de factura. No puede leer la tabla de clientes, no puede emitir reembolsos, no puede tocar otro servicio. El alcance es el radio de daño, puesto por escrito.
- Por agente. El agente de investigación y el de facturación tienen identidades distintas. Cuando algo se porta mal, sabes cuál agente fue y puedes revocar solo ese, sin tumbar la flota entera.
Por qué la combinación es lo que importa
La combinación pesa más que cualquier propiedad por separado:
- De vida corta pero sin acotar: un token robado puede hacer de todo, durante cinco minutos. Siguen siendo cinco minutos feos si ese "de todo" incluye mover dinero.
- Acotada pero eterna: una key estrecha que nunca muere, acumulando exposición en silencio dentro de logs y backups durante años.
- Por agente pero amplia y eterna: solo te dice con precisión cuál identidad sobredimensionada fue la que abusaron.
Quieres las tres, por identidad. Esa es la diferencia entre un incidente y una línea de log.
Atención
La comodidad es el enemigo aquí. En el momento en que a un nodo "de solo lectura" le pasan la credencial que mueve dinero "porque ya estaba ahí", tu acotamiento es puro teatro. El gestor tiene que lograr que el camino estrecho sea el camino fácil.
En Agent Orchestra, donde conectas muchos agentes en un mismo flujo de forma visual, esta es justo la parte fácil de hacer mal. Un nodo que "solo necesita leer una hoja" termina con la misma credencial amplia que el nodo que mueve dinero, porque era un clic menos de trabajo. El diseño correcto logra que pedir exactamente el alcance que necesitas sea más fácil que estirar la mano hacia el amplio.
04 · Rotación que no te despierta a las 3am
La rotación es donde mueren las buenas intenciones. El equipo acuerda que las keys deben rotar, pone un recordatorio trimestral y después nunca lo hace, porque rotar rompe cosas, y romper producción un viernes para tachar una casilla no es la idea de diversión de nadie.
Rotar rompe cosas cuando el secreto es un único valor referenciado en todas partes. Lo cambias y cada consumidor que clavó el literal viejo se cae al mismo tiempo. El arreglo es convertir la rotación en un evento normal que el sistema ya da por hecho.
- Emite credenciales con versión. Los consumidores piden la "actual", no un literal clavado.
- Cuando rotas, la versión nueva entra en vigor y la vieja pasa a una ventana de gracia en la que ambas son válidas.
- Los leases de larga vida emitidos con la versión vieja siguen funcionando hasta que expiran solos.
- Pasada la ventana de gracia, la versión vieja se revoca. Lo que siga usándola ya estaba roto; ahora te enteras, en tu horario, no a las 3am.
Como los agentes sacan leases cortos, la mayoría vuelve a sacar uno en minutos y toma la versión nueva sin que tengas que hacer nada. Rotar deja de ser una migración y se vuelve un martes cualquiera.
Consejo
Si rotar una credencial obliga a que un humano vuelva a hacer deploy de algo, no va a pasar a tiempo. Diséñalo para que el camino aburrido rote solo, y para que lo único que una rotación pueda romper sea algo que ya estaba roto.
Acá la propiedad de vida corta paga un segundo dividendo: la ventana de gracia puede ser corta porque nada retiene una credencial por mucho tiempo. Un sistema montado sobre keys estáticas necesita una ventana de gracia larga y nerviosa. Uno montado sobre leases de cinco minutos casi no necesita ninguna.
05 · Trazas de auditoría que de verdad puedas leer
Tarde o temprano vas a tener que responder una pregunta bajo presión: qué agente usó qué credencial, para hacer qué, y cuándo. Si no puedes responder eso rápido, no tienes seguridad, tienes fe.
La regla es simple: registra el lease, no el secreto. Cada lease guarda la identidad del agente, el alcance solicitado, el id de la tarea o ejecución, y un timestamp. Nunca el valor del token. Ese registro es la llave que une "un agente hizo algo" con "se usó una credencial".
// Una línea estructurada por lease. Sin token dentro.
log.info("vault.lease", {
agentId: ctx.agentId,
runId: ctx.runId,
scope: "billing:invoice.write",
ttlSeconds: 300,
ts: new Date().toISOString(),
})
Cuando salta una alerta, esto es lo que te permite acotar el incidente en minutos en vez de adivinar. Filtras por agente, ves exactamente qué alcances tenía y revocas su identidad. El daño ya está limitado por el mínimo privilegio que armaste en la sección 03; la traza de auditoría solo te permite demostrarlo y frenarlo rápido.
Una nota práctica: mantén estas líneas estructuradas y aburridas. La tentación es registrar de más, argumentos completos, payloads, resultados, y así es como los datos de un cliente, o peor, el mismísimo secreto que tanto cuidaste de mantener fuera del prompt, terminan en tu almacén de logs. Registra la metadata del acceso, no el contenido.
06 · Las concesiones, sin maquillaje
Esto es más maquinaria que una sola key en una variable de entorno, y ese costo es real. Fingir lo contrario es justo como terminas armando un gestor de secretos para un script de una sola vez.
- Latencia. Un lease por tarea agrega un ida y vuelta. Cachea dentro de una misma ejecución, nunca entre ejecuciones, y mantén el gestor cerca de los agentes. En nuestro VPS único detrás de Traefik, el gestor es un salto local, así que el overhead son unos pocos milisegundos. Por internet público no sería así: tenerlo todo en el mismo lugar está haciendo trabajo real acá.
- Una dependencia nueva. Si el gestor está caído, los agentes no pueden actuar. Trátalo como una base de datos: tiene que estar tan disponible como lo que protege, con la misma disciplina de backup y failover. Cambiaste un riesgo de filtración por una dependencia de disponibilidad, y por lo general ese cambio vale la pena, pero es un cambio que estás haciendo.
- Complejidad para trabajos chicos. Para un script personal que llama a una API tuya, todo esto es exagerado. Usa una variable de entorno y sigue. Estos patrones se ganan su lugar cuando tienes varios agentes, entrada no confiable, o credenciales que llegan a sistemas que odiarías perder.
Ajusta la ceremonia al radio de daño. El error, en ambas direcciones, es el mismo: tratar todas las credenciales por igual. Una API de clima de solo lectura y la key que mueve dinero no merecen la misma ceremonia, y una flota no merece la misma ceremonia que un cron.
Trata cada credencial que un agente pueda alcanzar como si ya estuviera filtrada, y después haz que eso salga barato. Mantén las keys completamente fuera del prompt, saca leases cortos, acota fino, separa identidades, y haz que rotar y auditar sean cosas aburridas. Si logras eso, un secreto filtrado se vuelve un token de cinco minutos para un alcance en un solo agente: una línea de log, no un incidente. Esa es toda la meta: no evitar cada filtración, sino asegurarte de que ninguna te salga cara.
Puntos clave
- Mantén las credenciales en crudo completamente fuera del modelo: el agente ve handles de herramientas, tu runtime resuelve los secretos fuera de la frontera del lenguaje.
- Haz las credenciales débiles a propósito: de vida corta, acotadas y por agente, las tres a la vez. Eso es lo que convierte un incidente en una línea de log.
- Diseña la rotación como un evento normal, con una 'actual' versionada y una ventana de gracia, para que el camino aburrido rote solo.
- Registra el lease, nunca el secreto, agente, alcance, run id, timestamp, para poder acotar y frenar un incidente en minutos.
- Ajusta la ceremonia al radio de daño: una env var para un script personal, toda la maquinaria para una flota que toca cosas que odiarías perder.
Preguntas frecuentes
¿Un token con lease no sigue siendo un secreto que el modelo podría filtrar?
No, porque el modelo nunca lo tiene en sus manos. El lease pasa en tu código de ejecución de herramientas, después de que el modelo emite el tool call. El token se adjunta al request saliente y se descarta; nunca entra a la ventana de contexto, así que no hay nada que una instrucción inyectada pueda repetir. El modelo maneja la intención, tu runtime maneja las credenciales.
¿Qué tan corto debe ser un lease en la práctica?
Tan corto como una sola tarea más un margen chico: minutos, no horas. Cachea dentro de una ejecución para no sacar un lease en cada llamada, pero nunca arrastres un lease de una ejecución a otra. Si una tarea de verdad dura mucho, saca otro lease a mitad de camino en lugar de emitir un token de larga vida. El número que importa es cuánto tiempo le sirve a alguien un token robado, y lo quieres tan corto que no le sirva de nada.
¿El gestor no se vuelve un único punto de fallo?
Sí, y lo tratas exactamente como a tu base de datos, porque funcionalmente es eso. Necesita la misma disponibilidad, backup y failover que los sistemas que protege. Cambias un riesgo de filtración por una dependencia de disponibilidad. Para una flota que toca algo que odiarías perder, por lo general ese cambio vale la pena, pero es una decisión explícita que debes tomar a propósito, no por accidente.
¿Cuándo todo esto es exagerado?
Cuando tienes un solo script que llama a una API tuya, sin entrada no confiable. Usa una variable de entorno y sigue: montar un gestor de secretos para eso es un error en sí mismo. Los patrones se ganan su lugar cuando tienes varios agentes, entrada no confiable, o credenciales que llegan a sistemas que odiarías perder. Ajusta la ceremonia al radio de daño, en ambas direcciones.
¿Y la latencia de sacar un lease en cada tarea?
Cachea dentro de una misma ejecución y mantén el gestor cerca de los agentes. En un VPS único detrás de Traefik el lease es un salto local, unos pocos milisegundos, así que el overhead es insignificante. Por internet público sí dolería, y ese es el verdadero argumento para colocar el gestor junto a las cargas que sirve. La latencia es un problema de ubicación, no una razón para saltarte el patrón.
¿Cómo se mapean los alcances con los permisos de un proveedor real?
Siempre que se pueda, apóyate en los tokens granulares del propio proveedor; por ejemplo, una API de pagos que emite keys restringidas por capacidad. Donde el proveedor solo ofrece una key amplia, el gestor pasa a ser la capa que la estrecha: guarda la credencial amplia, y el lease que le entrega a un agente queda limitado a exactamente una operación, forzada desde tu código de herramientas. El alcance que escribes en el lease debe ser el verbo-y-sustantivo más chico que la tarea necesita.
¿Prefieres que lo hagamos por ti?
Esto mismo lo construimos para negocios como el tuyo. La primera conversación es gratis y sin compromiso.
Escríbenos por WhatsAppPrimera conversación gratis. Te responde el fundador.
Recursos relacionados

Adopción de IA para líderes de TI: un plan que pone la seguridad primero sin frenar al negocio
Casi todos los consejos de adopción de IA los escribe gente que nunca cargó con un incidente. Este es el plan por etapas, aburrido y enfocado en entregar que de verdad ejecutaría dentro de una organización: límites de datos antes que herramientas, una revisión de proveedor que cabe en una semana, reemplazo en vez de prohibiciones, mínimo privilegio para los agentes y logs que de verdad llegas a leer.

Un MCP de bóveda de secretos que jamás devuelve texto plano
Apenas un modelo lee una API key en crudo dentro de su contexto, esa key ya quedó en los transcripts, en los logs y quizá en el próximo prompt, y eso no hay forma de deshacerlo. Un servidor MCP de bóveda de secretos cambia la forma misma del problema: los agentes operan con la credencial por referencia y el valor en crudo nunca llega al contexto del modelo. Este es el patrón detrás de Infuse, con la configuración, el modelo de autenticación y los modos de fallo bien explicados.

Un modelo de amenazas para agentes que usan herramientas
Un agente que solo conversa es de bajo riesgo. Un agente que puede llamar herramientas es software con un núcleo no determinista que hace llamadas privilegiadas, y te toca modelar sus amenazas como tal. Esta guía recorre los ataques que de verdad importan cuando un agente puede actuar (prompt injection, confused deputy, exfiltración de datos) y después arma la contención de mayor a menor eficacia: mínimo privilegio, aprobación humana en las acciones peligrosas y un muro sólido entre el contexto confiable y el no confiable.