Saltar al contenido
astorlm
Idioma: Español
← Mapa

Nivel 12

Planificar y reflexionar

Escribe el plan antes de tocar nada, y revisa el trabajo antes de aceptar la respuesta. El plan mantiene al agente encaminado; la revisión atrapa lo que dice que hizo pero no hizo.
1/52 Pliegues del bandoneón:
  • user
  • assistant
  • tool_result
Un reparto de diarios en la calle Tango. El kiosco es donde está el modelo, con la hoja de ruta clavada al lado: el plan. El editor es tu código.

EventBus

El problema

Dale a un agente un trabajo con varias partes y empieza por lo que tenga enfrente. A mitad de camino, los primeros pasos quedaron muy atrás en el historial, y se olvida de uno. Al final responde “¡listo!” con total seguridad, porque nada lo obliga a mirar.

Ese es Scatterbrain. Dos fallas en una: sin plan, así que se pierden pasos; sin verificación, así que un paso que salió mal se informa como hecho. En la calle Tango, la herramienta dijo claramente que el diario cayó entre los arbustos. El modelo lo leyó y marcó la casilla igual.

La solución

Primero, planificar. Antes de la primera acción real, el agente escribe el trabajo como una lista de tareas, y marca cada una a medida que avanza. El truco que lo hace funcionar: el plan completo se agrega a cada pedido, así el modelo siempre ve qué está hecho y qué falta, por más largo que se ponga el historial. En astorlm eso es pattern: 'PLAN_EXECUTE': dos herramientas, add_plan_item y update_plan_item, y el plan en el system prompt en cada turno.

Reflexionar antes de aceptar. Una casilla marcada es solo lo que dice el modelo. Cuando run() devuelve, tu código revisa el resultado antes de aceptarlo. Si falta algo, el hallazgo vuelve como un mensaje nuevo en la misma sesión: el agente conserva su historial y su plan, y arregla solo lo que está mal. Limita la cantidad de rondas. Hay tres formas de revisar, de la más fuerte a la más débil:

  • Revisar el mundo

    Tu código mira el resultado en sí: los porches, las filas de la base de datos, la suite de tests, el archivo en disco.

    El mejor revisor cuando puedes tenerlo: barato, exacto, y nadie puede convencerlo de nada. Necesita que el trabajo se pueda verificar con código.

  • Un modelo crítico

    Una segunda llamada lee la tarea, la respuesta y una lista de verificación, y enumera lo que está mal o falta.

    Para trabajo que ningún código puede verificar: un resumen, un email, un plan. Cuesta una llamada, también puede pasar cosas por alto, y necesita criterios concretos, no “¿esto está bien?”.

  • Preguntarle al agente

    El system prompt le dice al agente que relea su trabajo antes de responder.

    Gratis, y a veces alcanza. Pero es el mismo modelo calificándose a sí mismo, con los mismos puntos ciegos: ya marcó el #14 una vez.

Es la misma idea que una evaluación del nivel 11, usada en tiempo de ejecución: una evaluación califica ejecuciones después del hecho para mejorar el agente; una revisión califica esta ejecución antes de que el usuario la vea.

El elenco

El mismo elenco de siempre, esta vez en un reparto de diarios.

El kiosco el modelo
El Oráculo, detrás del mostrador. Decide cada paso, y nunca pedalea.
La hoja de ruta el plan
Las tareas y sus casillas. Brilla en dorado en cada turno: va en cada pedido.
La bici de Astor el bucle
Lleva cada llamada a herramienta de ida y vuelta, con el historial en su bandoneón.
Un lanzamiento deliver
Una herramienta común. Dice dónde cayó el diario.
El editor tu código
Entrega el trabajo, y revisa los porches antes de aceptar la respuesta. Su lupa es review().

El código

Con astorlm: pattern: 'PLAN_EXECUTE' agrega las herramientas del plan y pone el plan en cada pedido; getPlan() lo lee de vuelta. La revisión es código común después de run(), y un segundo run() sobre el mismo agente continúa la misma sesión.

Desde cero: Una lista, dos herramientas que la editan, y un system prompt que se reconstruye con la lista en cada turno. El historial vive fuera de run(), así que la corrección continúa la misma conversación.

import { OpenAIProvider, createLocalAgent, tool } from 'astorlm'
import { z } from 'zod'

// Any OpenAI-compatible endpoint: OpenAI, Ollama, LM Studio, vLLM, a proxy…
const LLM = { baseURL: 'http://localhost:11434/v1', apiKey: 'YOUR_API_KEY' } // local servers usually ignore the key

const SUBSCRIBERS = [12, 14, 18]
const porches = new Set<number>() // the real world: which porches have a paper

const deliver = tool({
  name: 'deliver',
  description: 'Ride to a house and throw today’s paper onto its porch. Says where the paper landed.',
  schema: z.object({ house: z.number() }),
  execute: async ({ house }) => {
    const landed = throwPaper(house) // your code: 'porch' or 'bushes'
    if (landed === 'porch') porches.add(house)
    return landed === 'porch' ? `Paper on the porch at #${house}.` : `Paper landed in the bushes at #${house}.`
  },
})

// PLAN: the agent gets add_plan_item and update_plan_item,
// and the current plan is added to the system prompt on every turn.
const agent = await createLocalAgent({
  provider: new OpenAIProvider({ ...LLM, model: 'your-model' }), // e.g. 'llama3.1', 'gpt-4o-mini'
  pattern: 'PLAN_EXECUTE',
  systemPrompt: 'You deliver newspapers. Plan every stop before you start, and tick each task as you go.',
  tools: [deliver],
  maxTurns: 20,
})

// REFLECT: check the work itself before accepting the answer. Deterministic when you can;
// a second model with a rubric when you can't.
const review = (): string[] => SUBSCRIBERS.filter((house) => !porches.has(house)).map((house) => `#${house} has no paper on the porch`)

let answer = await agent.run(`Deliver today’s paper to every subscriber on Tango Street: ${SUBSCRIBERS.join(', ')}.`)
for (let round = 1; round <= 2; round++) {
  const problems = review()
  if (problems.length === 0) break
  // Same agent, same session: it keeps its history and its plan, and fixes what's missing.
  answer = await agent.run(`Review found: ${problems.join('; ')}. Fix it.`)
}

console.log(agent.getPlan()) // [{ id: '1', description: 'Deliver to #12', status: 'completed' }, …]
console.log(answer.content)

Qué vigilar

  • Mantén las tareas chicas y verificables. “Entregar en el #14” se puede verificar; “encargarse de la calle”, no. Una tarea que puedes verificar es una tarea que la revisión puede atrapar.
  • Deja que el plan cambie. Los planes chocan con la realidad: una calle está cortada, un cliente cancela. El agente debería poder agregar, quitar o reordenar tareas, no seguir una lista desactualizada.
  • Revisa el mundo, no el plan. La hoja decía tres marcas. Revisar la hoja habría pasado. La revisión tiene que mirar el resultado en sí.
  • Limita las rondas. Una revisión que nunca puede pasar, o un agente que no puede arreglar lo que encuentra, da vueltas para siempre. Dos o tres rondas, y después pásaselo a una persona (nivel 13).
  • No planifiques algo de una línea. Planificar cuesta turnos y tokens. Para una sola consulta, sáltatelo. Vale la pena cuando el trabajo tiene varios pasos fáciles de perder.