¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Estado compartido entre agentes

Después de esta lección: Puedo dejar que los agentes compartan un registro sin pisarse, y avisar de los conflictos.

Lección de 60 min7 comandosLaboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

Dos agentes, un registro, una escritura perdida

El estado compartido es un registro que leen y escriben varios agentes. Importa porque dos agentes que leen a la vez y luego escriben a la vez pueden borrarse el trabajo sin que nadie lo note.

No falla nada. El registro se queda con la última escritura, y un buen hallazgo desaparece.

Al final de esta lección

Nota

Puedo dejar que los agentes compartan un registro sin pisarse, y avisar de los conflictos.

Palabras clave

PalabraQué significa
Registro compartidouna sola copia de los hechos que todos los agentes leen y escriben
Mensajetexto que un agente envía a otro
Versiónun número que sube con cada escritura aceptada
Versión basela versión que leyó quien escribe antes de escribir
Conflictouna escritura basada en un campo que cambió después
Actualización perdidauna escritura que borra otra sin que se vea

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Mensajes o un registro compartido

Los agentes pueden pasarse mensajes. Cada uno guarda su copia de lo que ha oído y nada entra en conflicto, pero las copias se van separando.

O pueden compartir un registro. Hay una sola verdad, pero dos autores pueden chocar. La mayoría de los equipos necesita las dos cosas: mensajes para decir qué hacer, un registro para lo que se sabe.

Ejemplo resuelto: mensajes y registro

MensajesRegistro compartido
Quién guarda los hechosCada agente, por separadoUn solo sitio
¿Pueden discrepar dos agentes?Sí, y nadie lo sabeNo, hay un solo valor
¿Puede perderse una escritura?NoSí, si no se comprueban las escrituras
Mejor paraDecir a un trabajador qué hacerLo que el equipo ha encontrado hasta ahora

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Una escritura nombra la versión que leyó

Da una versión a cada campo. Cuando un agente lee, guarda la versión. Cuando escribe, devuelve esa versión base.

El registro acepta la escritura solo si el campo no ha cambiado desde entonces. Si no, responde con un conflicto, y el agente vuelve a leer y decide. Un campo que nadie ha escrito no puede entrar en conflicto.

Un error frecuente

Advertencia

Mucha gente resuelve un conflicto dejando ganar la última escritura. Eso es la actualización perdida, con una línea de registro más. Un conflicto es una pregunta para quien escribe: leer el valor nuevo y luego decidir.

Escribir el ayudante del modelo, parte 1

Comando
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.

Escribir el ayudante del modelo, parte 2

Comando
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.

Escribir el registro compartido, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const record = { version: 0, fields: {} };' 'function read() {' '  return { version: record.version, fields: JSON.parse(JSON.stringify(record.fields)) };' '}' > state.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir el registro compartido, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' '// Una escritura nombra la versión que leyó. Solo vale si nadie cambió ese campo desde entonces.' 'function write(agent, field, value, base) {' '  const f = record.fields[field];' '  const word = \" escribe \" + field + \" desde la versión \" + base + \": \";' '  if (f && f.version > base) {' '    console.log(agent + word + \"CONFLICTO, en la versión \" + f.version + \" por \" + f.by);' '    return false;' '  }' '  record.version += 1;' '  record.fields[field] = { value: value, version: record.version, by: agent };' '  console.log(agent + word + \"aplicada, registro en la versión \" + record.version);' '  return true;' '}' >> state.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir el registro compartido, parte 3

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  const a = read();' '  const b = read();' '  write(\"precios\", \"coste\", \"108 euros\", a.version);' '  if (write(\"lector\", \"coste\", \"120 euros\", b.version) === false) {' '    const again = read();' '    console.log(\"lector vuelve a leer: coste es \" + again.fields.coste.value + \" en la versión \" + again.version);' '    write(\"lector\", \"coste_nota\", \"la segunda cifra era 120\", again.version);' '  }' '  write(\"lector\", \"quieren\", \"212 de 400\", b.version);' '  await last();' '}' >> state.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir el registro compartido, parte 4

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function last() {' '  const q = [{ role: \"user\", content: \"Escribe una nota de menos de 12 palabras que diga que dos cifras de un mismo coste no coinciden.\" }];' '  const note = (await ask(q, \"Dos cifras de un mismo coste no coinciden: revisa la fuente.\", 30)).text.trim();' '  write(\"revisor\", \"nota\", note, record.version);' '  const names = Object.keys(record.fields);' '  console.log(\"Campos: \" + names.map(function (k) { return k + \"@\" + record.fields[k].version; }).join(\", \"));' '}' 'main();' >> state.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ejecutar el registro compartido

Comando
docker exec -w /home/node/project agent node state.js

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Es un sustituto

El laboratorio no tiene base de datos, así que el registro es un objeto del script. Un equipo real usa una base de datos que hace esta comprobación en un solo paso. Comprobar y luego escribir en dos pasos deja un hueco a otro autor.

La única llamada en vivo redacta una nota. Sus palabras cambian en cada ejecución.

Una salida posible

LíneaQué muestra
precios escribe coste desde la versión 0: aplicada, registro en la versión 1Gana el primer autor
lector escribe coste desde la versión 0: CONFLICTO, en la versión 1 por preciosEl segundo había leído una versión antigua
lector vuelve a leer: coste es 108 euros en la versión 1Tras el conflicto, lee el valor nuevo y decide
lector escribe coste_nota desde la versión 1: aplicada, registro en la versión 2Tras leer de nuevo, escribe una nota
lector escribe quieren desde la versión 0: aplicada, registro en la versión 3Un campo nuevo no puede dar conflicto
revisor escribe nota desde la versión 3: aplicada, registro en la versión 4Escribe una nota nueva, con la versión actual
Campos: coste@1, coste_nota@2, quieren@3, nota@4La versión en que se escribió cada campo

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Sobre este laboratorio y su código: Laboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.