💻 Todo el código de esta serie está en un solo repo: resilient-agent-harness-sample-for-aws. Este post es la demo de Multi-Step Task Planning (
03-multi-step-task-planning). Clona el repo y sigue el paso a paso.
Dale a un agente de IA una tarea con varios pasos y una herramienta que se porta mal en silencio, y esto es lo que pasa: el paso de una herramienta devuelve "confirmed", el agente lo cree, sigue adelante, y al final reporta toda la tarea completada. Pero ese paso nunca persistió realmente. La herramienta dijo éxito; la escritura no está ahí. El agente no tiene forma de distinguir un éxito real de uno falso, así que entrega un resultado que está parcialmente roto con toda confianza.
Confiar en el "confirmed" de una herramienta sin verificar es una de las formas más comunes en que los agentes fallan en trabajo multi-paso. El fallo es invisible precisamente porque nada dio error. No hay excepción que atrapar, no hay línea roja en el log, solo un resumen alegre que no coincide con la realidad. Y no puedes resolver esto con un prompt. La corrección es estructural: verificar cada paso contra el backend real, y re-hacer el que no persistió.
Para hacerlo concreto, construí un pequeño agente de viajes y le di un viaje para reservar. La demo completa, ejecutable de principio a fin, está en el repo resilient-agent-harness.
¿Cuál es la demo?
El agente, construido con Strands Agents, reserva un viaje alrededor del mundo de tres vuelos (JFK a CDG, CDG a HND, HND a JFK) y tiene tres herramientas:
-
search_flightsencuentra tarifas en el sandbox de Duffel. -
book_flightescribe una reserva en el backend. El vuelo del medio (CDG a HND, el tramo a Tokio) tiene un fallo silencioso integrado: su primer intento devuelve"confirmed"pero no guarda. -
list_booked_flightslee lo que realmente persistió. Este es el ground truth.
Antes de que cualquier agente corra, el notebook llama a book_flight en el vuelo de Tokio directamente para probar la trampa: el intento 1 dice confirmed, pero list_booked_flights muestra que la reserva no está ahí. Ese es el fallo silencioso, demostrado en la herramienta misma, para que confíes en el resto de la historia.
¿Qué es la planificación de tareas multi-paso?
La planificación de tareas multi-paso es completar una tarea hecha de varios pasos ordenados ejecutando un paso, verificando que realmente persistió en el backend real, y solo entonces pasando al siguiente, en lugar de disparar todos los pasos y confiar en el éxito reportado de cada herramienta. La verificación contra el ground truth es lo que atrapa un paso que reportó "listo" pero silenciosamente nunca se guardó.
La trampa es que la respuesta de una herramienta y el estado real del mundo pueden no coincidir. Una llamada de reserva puede devolver una confirmación mientras la fila nunca llega. Verificar contra el backend es la única forma confiable de saber la diferencia.
¿Por qué el "confirmed" de una herramienta no es suficiente?
Una herramienta puede devolver éxito mientras la escritura no persistió: un backend inestable, un lag de consistencia, una transacción a medio aplicar. La respuesta se ve idéntica a un éxito real, así que el agente la reporta como hecho. La demo ejecuta el viaje de dos formas:
| Enfoque | Cómo funciona | Qué pasa |
|---|---|---|
| ANTES | Un agente reserva los tres vuelos y confía en cada "confirmed". |
Reporta el viaje reservado, pero solo 2/3 vuelos realmente se guardaron (JFK-CDG, HND-JFK). El vuelo a Tokio falta silenciosamente. |
| DESPUÉS | Un Graph nativo de Strands: un executor reserva un vuelo, un verifier lee el backend y responde PASS/FAIL, y un edge condicional reintenta ante FAIL. | El verifier atrapa el fallo silencioso y el graph re-reserva. 3/3 vuelos realmente guardados. |
Por qué un Graph, y por qué Strands lo hace fácil
Coordinar dos agentes (un executor que hace el trabajo y un verifier que lo verifica, con un retry cuando la verificación falla) es orquestación multi-agente. Eso es exactamente para lo que sirve el GraphBuilder nativo de Strands, y es donde Strands hace el trabajo pesado por ti. Los docs describen un Graph como un sistema determinista de orquestación de agentes donde el executor y el verifier son nodos y el flujo entre ellos son edges, incluyendo edges condicionales y cíclicos. El patrón de retry-hasta-que-se-guarde es el que los docs llaman "feedback loop": declaras los nodos y edges, y el SDK ejecuta el flujo, el loop de retry acotado, y la contabilidad de tokens. No necesitas armar un while a mano ni rastrear estado tú mismo.
El diagrama muestra ese loop: el executor reserva un vuelo y pasa al verifier; el verifier lee el backend real; un edge verde PASS termina el vuelo, y un edge rojo FAIL regresa al executor para re-reservar. GraphBuilder cablea el edge condicional y acota el ciclo para que no pueda girar infinitamente.
Dos decisiones de diseño cargan todo. El verifier tiene solo list_booked_flights, así que decide desde el ground truth, no desde lo que dijo el executor. Y el retry es un edge condicional de verify de vuelta a execute que solo se dispara cuando el verifier leyó FAIL. set_max_node_executions(6) acota el loop (requerido para un ciclo), y reset_on_revisit(True) hace que el executor arranque limpio en cada retry en vez de cargar estado viejo.
from strands import Agent
from strands.multiagent import GraphBuilder
executor = Agent(name="executor", tools=[search_flights, book_flight])
verifier = Agent(name="verifier", tools=[list_booked_flights]) # lee ground truth, responde PASS/FAIL
def verification_failed(state):
v = state.results.get("verify")
return bool(v) and "FAIL" in str(v.result).upper()
builder = GraphBuilder()
builder.add_node(executor, "execute")
builder.add_node(verifier, "verify")
builder.add_edge("execute", "verify")
builder.add_edge("verify", "execute", condition=verification_failed) # retry solo en FAIL
builder.set_entry_point("execute")
builder.set_max_node_executions(6) # acota el loop de retry (requerido para un ciclo)
builder.reset_on_revisit(True) # executor arranca limpio cada retry
graph = builder.build()
result = graph(f"Book flight {route} and verify it actually saved.")
Puedes ver la recuperación en la traza por vuelo. Los dos vuelos que se guardan en el primer intento ejecutan execute, verify y paran. El vuelo a Tokio ejecuta execute, verify, execute, verify: el verifier leyó FAIL, el edge condicional regresó, y el executor lo re-reservó.
JFK-CDG: nodes ran -> ['execute', 'verify'] saved = True
CDG-HND: nodes ran -> ['execute', 'verify', 'execute', 'verify'] saved = True # reintentó!
HND-JFK: nodes ran -> ['execute', 'verify'] saved = True
flights ACTUALLY saved in the backend: 3/3
¿La verificación cuesta más tokens?
Sí, y esa es la parte que la mayoría de posts de "eficiencia de agentes" se salta. Los tokens vienen de result.accumulated_usage, las métricas reales de Strands, no estimaciones. Una ejecución medida en OpenAI gpt-4o-mini me dio:
| antes | después | |
|---|---|---|
| vuelos realmente guardados | 2/3 | 3/3 |
| el agente declaró completo | sí | sí |
| tokens | 3,126 | 10,732 |
Léelo honestamente: la verificación cuesta más tokens, no menos, porque pagas por leer el backend y reintentar. Ambas ejecuciones declaran "todo reservado"; solo el Graph verificado realmente está bien. La ganancia es correctitud, no una factura más pequeña. Los totales exactos varían por ejecución porque el modelo es no-determinista, así que ejecútalo tú mismo y observa cómo se mantiene la forma: el agente ANTES es más barato y está mal, el graph DESPUÉS cuesta más y entrega un viaje completo.
Preguntas frecuentes
¿Por qué el "confirmed" de una herramienta no es suficiente?
Porque una herramienta puede devolver éxito mientras la escritura no persistió realmente (un backend inestable, un lag de consistencia). El agente no puede distinguir un éxito real de uno falso, así que reporta trabajo como hecho que no lo está. Leer el backend después del hecho es la única verificación confiable.
¿La verificación siempre cuesta más tokens?
Sí, de entrada, y ese es el trade. Gastas tokens extra para leer el backend y reintentar, y a cambio no entregas un viaje al que silenciosamente le falta un vuelo. La métrica que importa es correctitud, no el conteo crudo de tokens.
¿Necesito Strands u OpenAI para esto?
No. Ejecutar, verificar contra ground truth, y reintentar el fallo son conceptos generales de agentes. Strands es agnóstico al modelo: sus proveedores son intercambiables, así que el mismo Graph corre en Amazon Bedrock (el default), Anthropic, OpenAI, o un modelo local vía Ollama. La demo usa OpenAI gpt-4o-mini por defecto porque solo necesita una API key para probar, aunque eso sigue siendo una llamada a la nube, no un modelo en tu máquina.
Ejecútalo tú mismo
La demo completa (el fallo silencioso probado directamente en la herramienta, el agente naive entregando 2/3, luego el Graph nativo recuperando a 3/3) corre de principio a fin en un solo notebook. Clona el repo y ejecútalo:
git clone https://github.com/elizabethfuentes12/resilient-agent-harness-sample-for-aws.git
cd resilient-agent-harness-sample-for-aws/03-multi-step-task-planning
uv venv && source .venv/bin/activate
uv pip install -r requirements.txt
# Default: OpenAI gpt-4o-mini (solo necesitas una API key para probar)
echo "OPENAI_API_KEY=sk-..." > .env
echo "DUFFEL_API_KEY=duffel_test_..." >> .env # token sandbox gratuito de app.duffel.com
uv run test_multi_step_task_planning.py
¿Prefieres notebooks? Abre test_multi_step_task_planning.ipynb y ejecútalo de arriba a abajo.
El patrón sigue a MiRA (Wang et al., Mar 2026), que agrega planificación y verificación en tiempo de inferencia sin entrenamiento. Las cifras de benchmark y la lectura completa están en el README del repo. Lo que esta demo produce es el mecanismo: ejecutar, verificar contra ground truth, reintentar el fallo, en un Graph nativo de Strands.
¿Cuál es el fallo silencioso que mordió a tu agente: una herramienta que dijo "listo" mientras nada se guardó? Cuéntame en los comentarios.
📬 ¿Construyes agentes de IA confiables? Escribo sobre memoria de agentes, guardrails, evaluación y patrones multi-agente. Suscríbete a mi newsletter para recibir el siguiente.
¡Gracias!
🇻🇪 Dev.to Linkedin GitHub Twitter Instagram Youtube

Top comments (0)