Una lista antes de entregar un agente
Una revisión de seguridad comprueba el diseño de un agente con una lista antes de usarlo. Cada punto es una pregunta con respuesta sí o no, así que dos revisores llegan al mismo resultado.
Importa porque las lecciones de este módulo solo ayudan si están todas puestas. Un diseño con buena carpeta pero sin forma de pararlo sigue siendo inseguro.
Al final de esta lección
Nota
Puedo revisar el diseño de un agente con una lista de comprobación.
Palabras clave
| Palabra | Qué significa |
|---|---|
| Lista de comprobación | una lista fija de preguntas de sí o no |
| Diseño | qué herramientas, datos y límites tiene un agente |
| Límite | un tope de pasos o de coste |
| Interruptor de parada | una forma de que una persona detenga al agente |
| Registro | una anotación de lo que hizo el agente |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Seis áreas, ocho preguntas
La lista cubre seis áreas: herramientas, datos, carpetas, límites, una forma de parar y un registro. Cada área tiene una o más preguntas de sí o no.
Un diseño aprueba solo si pasa todas las preguntas. Informa de cada fallo con su área, para que el arreglo sea fácil de encontrar.
Ejemplo resuelto: tres diseños
| Diseño | Fallos | Cuáles |
|---|---|---|
| asistente | 0 | Ninguno: aprueba |
| constructor | 4 | Tiene una herramienta shell, escribe en cualquier sitio, sin límite de pasos, sin registro |
| explorador | 5 | Sin lista de herramientas, secretos en la instrucción, sin límites, sin parada |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Un error frecuente
Advertencia
Mucha gente cree que un solo control fuerte hace seguro un diseño. No es así. El constructor tiene interruptor de parada y un límite de coste, pero tiene shell y escribe en cualquier sitio. La seguridad son capas, y la capa débil que falta es la primera que falla.
Los números necesitan un borde
Un límite solo es una comprobación si tiene un borde. Aquí una ejecución puede dar 20 pasos como máximo. Un diseño con 20 aprueba. Uno con 21, o sin límite, falla.
Di dónde está el borde, pruébalo por los dos lados y cuenta un valor que falta como un fallo.
Escribe el ayudante del modelo, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// Los tokens de una respuesta, o null si no trae ninguno.' 'function count(data, name) {' ' return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > model.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el ayudante del modelo, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function ask(messages, sample, max) {' ' try {' ' const res = await fetch(base + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"estado \" + res.status);' ' const d = await res.json();' ' return { text: d.choices[0].message.content, inTokens: count(d, \"prompt_tokens\"), outTokens: count(d, \"completion_tokens\"), recorded: false };' ' } catch (error) {' ' console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' ' return { text: sample, inTokens: null, outTokens: null, recorded: true };' ' }' '}' 'module.exports = { ask };' >> model.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el comprobador de diseños, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const checks = [' ' [\"herramientas: sin lista permitida\", function (d) { return d.allowlist === false; }],' ' [\"herramientas: tiene shell\", function (d) { return d.tools.indexOf(\"shell\") >= 0; }],' ' [\"carpetas: la escritura no está confinada\", function (d) { return d.canWrite && (d.root === \"\" || d.root === \"/\"); }],' ' [\"datos: secretos en la instrucción\", function (d) { return d.secrets; }],' ' [\"límites: sin límite de pasos\", function (d) { return d.maxSteps === null || d.maxSteps > 20; }],' ' [\"límites: sin límite de coste\", function (d) { return d.maxCost === null; }],' ' [\"parada: sin forma de parar\", function (d) { return d.stop === false; }],' ' [\"registro: sin log\", function (d) { return d.log === false; }],' '];' 'function failures(d) { return checks.filter(function (c) { return c[1](d); }).map(function (c) { return c[0]; }); }' > review.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el comprobador de diseños, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const designs = [' ' { name: \"asistente\", tools: [\"read\", \"write\"], allowlist: true, canWrite: true, root: \"trabajo/\", secrets: false, maxSteps: 10, maxCost: 5, stop: true, log: true },' ' { name: \"constructor\", tools: [\"read\", \"write\", \"shell\"], allowlist: true, canWrite: true, root: \"/\", secrets: false, maxSteps: null, maxCost: 20, stop: true, log: false },' ' { name: \"explorador\", tools: [\"search\"], allowlist: false, canWrite: false, root: \"\", secrets: true, maxSteps: 50, maxCost: null, stop: false, log: true },' '];' >> review.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el comprobador de diseños, parte 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' designs.forEach(function (d) {' ' const f = failures(d);' ' console.log(d.name + \": \" + f.length + \" fallos\" + (f.length > 0 ? \": \" + f.join(\"; \") : \"\"));' ' });' ' const q = \"En una frase corta: ¿por qué un agente debe tener una forma de pararlo?\";' ' const sample = \"Si algo sale mal, una persona tiene que poder detenerlo al instante y ver qué hizo.\";' ' const reply = await ask([{ role: \"user\", content: q }], sample, 60);' ' console.log(\"el modelo dijo: \" + reply.text);' '}' 'main();' >> review.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejecuta el comprobador de diseños
docker exec -w /home/node/project agent node review.jsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Lo que imprime el Run
| Línea | Qué muestra |
|---|---|
| asistente: 0 fallos | Pasa todas las comprobaciones |
| constructor: 4 fallos: herramientas: tiene shell; ... | Falla en cuatro áreas |
| explorador: 5 fallos: herramientas: sin lista permitida; ... | Es el que más falla |
| el modelo dijo: ... | Una frase. Las palabras cambian en cada ejecución |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.