Cómo los agentes planifican tareas con listas de tareas pendientes

todos lo hacemos de forma natural y regular. En nuestra vida personal, a menudo tenemos listas de tareas pendientes para organizar vacaciones, recados y todo lo demás.

En el trabajo, confiamos en rastreadores de tareas y planes de proyectos para mantener alineados a los equipos. Para los desarrolladores, también es común dejar comentarios TODO en el código como recordatorios para cambios futuros.

Como era de esperar, los agentes de LLM también se benefician de listas claras de tareas pendientes para guiar su planificación.

Las listas de tareas pendientes ayudan a los agentes a planificar y realizar un seguimiento de tareas complejas de manera más efectiva, lo que las hace especialmente útiles para la coordinación de múltiples herramientas y operaciones de larga duración donde el progreso debe ser visible.

Agentes de codificación como OpenAI Codex, Cline y Claude Code (que uso habitualmente) son excelentes ejemplos de este concepto.

Dividen las solicitudes complejas en un conjunto inicial de pasos, las organizan como una lista de tareas pendientes con dependencias y actualizan el plan en tiempo real a medida que se completan las tareas o surge nueva información.

Ejemplo de un plan generado por el agente Claude Code (Claude-4.5-sonnet) en el panel derecho de Cursor | Imagen del autor

Esta claridad permite a los agentes manejar largas secuencias de acciones, coordinar diferentes herramientas y realizar un seguimiento del progreso de una manera comprensible.

En este artículo, profundizamos en cómo los agentes utilizan las capacidades de la lista de tareas pendientes, analizamos los componentes subyacentes del proceso de planificación y demostramos su implementación con LangChain.

Contenido

(1) Escenario de ejemplo para el agente de planificación
(2) Componentes clave de las capacidades de tareas pendientes
(3) Armarlo en un Middleware

El código adjunto está disponible en este repositorio de GitHub.

(1) Escenario de ejemplo para el agente de planificación

Veamos el escenario de ejemplo para anclar nuestro tutorial.

Configuraremos un único agente para planificar un itinerario de viaje y ejecutar las tareas de reserva. El agente tiene acceso a:

En este ejemplo, se burlan de estas herramientas y no realizan reservas reales; se incluyen para ilustrar la lógica de planificación del agente y cómo utiliza las listas de tareas pendientes.

Aquí está el código para implementar nuestro agente de planificación en LangChain:

Ingresamos una consulta de usuario y vemos la lista de tareas pendientes resultante de la planificación del agente:

Lista de tareas pendientes generada por el agente de planificación de viajes

El uso de la toma de notas estructurada a través de listas de tareas pendientes permite a los agentes mantener una memoria persistente fuera de la ventana contextual. Esta estrategia mejora la capacidad de un agente para gestionar y retener el contexto relevante a lo largo del tiempo.

La configuración del código es sencilla: create_agent crea la instancia del agente LLM, pasamos el mensaje del sistema, seleccionamos el modelo (GPT-5.1) y vinculamos las herramientas.

Lo que es digno de mención es el objeto TodoListMiddleware() que se pasa al parámetro de middleware.

En primer lugar, ¿qué es el middleware de LangChain?

Como sugiere el nombre, es una capa intermedia que le permite ejecutar código personalizado antes y después de las llamadas LLM.

Piense en el middleware como una capa programable que nos permite inyectar código para monitorear, ajustar o ampliar su comportamiento.

Nos brinda control y visibilidad sobre los comportamientos de los agentes sin cambiar su lógica central. Se puede utilizar para transformar indicaciones y resultados, gestionar reintentos o salidas anticipadas y aplicar salvaguardas (p. ej., barreras de seguridad, comprobaciones de PII).

TodoListMiddleware es un middleware integrado que proporciona específicamente capacidades de administración de listas de tareas a los agentes. A continuación, exploramos cómo funciona TodoListMiddleware en su interior.

(2) Componentes clave de las capacidades de tareas pendientes

Las capacidades de gestión de la lista de tareas pendientes de un agente de planificación se reducen a estos cuatro componentes clave:

Elemento de tarea pendiente Lista de elementos pendientes Una herramienta que escribe y actualiza la lista de tareas pendientes Actualización del mensaje del sistema de tareas pendientes

TodoListMiddleware reúne estos elementos para habilitar las capacidades de la lista de tareas pendientes de un agente.

Echemos un vistazo más de cerca a cada componente y cómo se implementa en el código del middleware de tareas pendientes.

(2.1) Elemento de tarea pendiente

Una tarea pendiente es la unidad más pequeña de una lista de tareas pendientes y representa una sola tarea. Está representado por dos campos: descripción de la tarea y estado actual.

En LangChain, esto se modela como un tipo Todo, definido usando TypedDict:

El campo de contenido representa la descripción de la tarea que el agente debe realizar a continuación, mientras que el estado rastrea si la tarea no se ha iniciado (pendiente), en la que se está trabajando (en progreso) o finalizada (completada).

A continuación se muestra un ejemplo de una tarea pendiente:

{ “content”: “Comparar opciones de vuelo de Singapur a Tokio”, “status”: “completado” },

(2.2) Lista de tareas pendientes

Ahora que hemos definido la estructura de una tarea pendiente, exploramos cómo se almacena y rastrea un conjunto de tareas pendientes como parte del plan general.

Definimos un objeto Estado (PlanningState) para capturar el plan como una lista de tareas pendientes, que se actualizará a medida que se realicen las tareas:

El campo todos es opcional (No requerido), lo que significa que puede estar ausente cuando se inicializa por primera vez (es decir, es posible que el agente aún no tenga ninguna tarea en su plan).

OmitFromInput significa que todo se administra internamente mediante el middleware y no debe proporcionarse directamente como entrada del usuario.

El estado es la memoria a corto plazo del agente, que captura conversaciones recientes e información clave para que pueda actuar de manera apropiada en función del contexto y la información anteriores.

En este caso, la lista de tareas pendientes permanece dentro del estado para que el agente pueda consultar y actualizar las tareas de manera consistente durante toda la sesión.

A continuación se muestra un ejemplo de una lista de tareas pendientes:

todos: lista[Todo] = [
{
“content”: “Research visa requirements for Singapore passport holders visiting Japan”,
“status”: “completed”
},
{
“content”: “Compare flight options from Singapore to Tokyo”,
“status”: “in_progress”
},
{
“content”: “Book flights and hotels once itinerary is finalized”,
“status”: “pending”
}
]

(2.3) Herramienta para escribir y actualizar tareas pendientes

Una vez establecida la estructura básica de la lista de tareas pendientes, ahora necesitamos una herramienta para que el agente de LLM la administre y actualice a medida que se ejecutan las tareas.

Esta es la forma estándar de definir nuestra herramienta (write_todos):

La herramienta write_todos devuelve un comando que indica al agente que actualice su lista de tareas pendientes y agregue un mensaje que registre el cambio.

Si bien la estructura write_todos es sencilla, la magia reside en la descripción (WRITE_TODOS_TOOL_DESCRIPTION) de la herramienta.

Cuando el agente llama a la herramienta, la descripción de la herramienta sirve como mensaje adicional crítico, guiándolo sobre cómo usarla correctamente y qué entradas proporcionar.

Aquí está la expresión (bastante larga) de LangChain de la descripción de la herramienta:

Podemos ver que la descripción es muy estructurada y precisa, definiendo cuándo y cómo utilizar la herramienta, estados de tareas y reglas de gestión.

También proporciona directrices claras para realizar un seguimiento de tareas complejas, dividirlas en pasos claros y actualizarlas sistemáticamente.

No dude en consultar la interpretación más sucinta de Deepagents de la descripción de una herramienta de tareas pendientes aquí

(2.4) Actualización del mensaje del sistema

El último elemento de configuración de la capacidad de tareas pendientes es actualizar el mensaje del sistema del agente.

Se realiza inyectando WRITE_TODOS_SYSTEM_PROMPT en el mensaje principal, informando explícitamente al agente que existe la herramienta write_todos.

Guía al agente sobre cuándo y por qué usar la herramienta, proporciona contexto para tareas complejas de varios pasos y describe las mejores prácticas para mantener y actualizar la lista de tareas pendientes:

(3) Armarlo en un Middleware

Finalmente, los cuatro componentes clave se reúnen en una única clase llamada TodoListMiddleware, que empaqueta las capacidades de tareas pendientes en un flujo coherente para el agente:

Definir PlanningState para realizar un seguimiento de las tareas como parte de una lista de tareas pendientes Crear dinámicamente la herramienta write_todos para actualizar la lista y hacerla accesible al LLM Inyectar WRITE_TODOS_SYSTEM_PROMPT para guiar la planificación y el razonamiento del agente

WRITE_TODOS_SYSTEM_PROMPT se inyecta a través del método wrap_model_call (y awrap_model_call) del middleware, que lo agrega al mensaje del sistema del agente para cada llamada al modelo, como se muestra a continuación:

Envolviéndolo

Al igual que los humanos, los agentes utilizan listas de tareas pendientes para desglosar problemas complejos, mantenerse organizados y adaptarse en tiempo real, lo que les permite resolver problemas de forma más eficaz y precisa.

A través de la implementación de middleware de LangChain, también obtenemos una visión más profunda de cómo los agentes pueden estructurar, rastrear y ejecutar las tareas planificadas.

Consulte este repositorio de GitHub para conocer la implementación del código.