Agentes 101 - 02: El ciclo del agente como State Machine (y Hierarchical State Machines) A developer explains that an LLM agent's cycle can be modeled as a finite state machine (FSM) or hierarchical state machine (HSM), with states like thinking, acting, observing, done, and error. The post argues that understanding these state machine concepts leads to clearer and more scalable agent designs, and that tools like LangGraph implement this approach cleanly. En el artículo anterior definimos un agente de forma práctica: Un agente LLM es un modelo dentro de un ciclodonde puede razonar, actuar, observar el resultado y decidir qué hacer después. Esa definición es correcta. Pero todavía es demasiado abstracta. Hoy mucha gente está construyendo agentes con vibe coding . Le pide al modelo que le arme un agente, copia el código y sigue. Los modelos actuales son realmente buenos escribiendo código, y eso hace que el proceso se sienta mágico. El problema es que muchas veces se termina implementando algo sin entender los conceptos base. Y cuando no se entienden los conceptos, el modelo puede proponer soluciones más complejas de lo necesario. Por ejemplo, sugerirte una Hierarchical State Machine cuando una Finite State Machine simple habría sido más que suficiente y capaz ni siquiera te das cuenta de que es una FSM o HSM .. Por eso este artículo. No para complicar las cosas, sino para tener claridad sobre qué estamos construyendo realmente. La pregunta central es: ¿Cómo modelamos el ciclo de un agente de forma explícita, controlable y escalable? La respuesta es: tratarlo como una máquina de estados . Imaginemos el flujo más simple de un agente: Ese flujo se puede modelar perfectamente como una Finite State Machine FSM : | Estado | Descripción | |---|---| 'thinking' | El modelo está razonando | 'acting' | Está ejecutando una herramienta | 'observing' | Está procesando el resultado | 'done' | Terminó la tarea | 'error' | Algo falló | Las transiciones dependen del resultado de cada paso. Eso es exactamente lo que hace un agente. Aquí un ejemplo conceptual pseudo-código : state = { "task": "Implementar CORS en API Gateway con CDK", "code": "", "last observation": None, "status": "thinking" } while state "status" not in "done", "error" : if state "status" == "thinking": decision = llm.think state if decision.needs tool: state "status" = "acting" state "next tool" = decision.tool else: state "status" = "done" state "final answer" = decision.answer elif state "status" == "acting": result = run tool state "next tool" , state state "last observation" = result state "status" = "observing" elif state "status" == "observing": El modelo decide qué hacer con la observación next action = llm.observe state state "status" = next action puede ser "thinking", "done", "error"... Este patrón es el corazón de casi todos los frameworks de agentes. La diferencia está en qué tan explícito se hace el control del estado. Las herramientas no son un "extra". Son acciones que producen una observación y, por lo tanto, cambian el estado de la máquina. Cuando el agente llama a search docs o run tests , lo que realmente está haciendo es: thinking acting Si pensamos las tools de esta forma, el diseño se vuelve mucho más claro: Una FSM plana funciona bien para agentes simples. Pero cuando el agente crece, empiezan a aparecer problemas: Aquí es donde aparecen las Hierarchical State Machines HSM . La idea es simple: un estado puede contener otra máquina de estados completa. Ejemplo: resolver tarea estado de alto nivel ├── investigar │ ├── buscar documentación │ ├── analizar código existente │ └── sintetizar hallazgos ├── implementar │ ├── escribir código │ └── correr tests │ └── corregir errores └── validar ├── revisar calidad └── generar respuesta final Cada sub-máquina tiene su propio estado interno, pero el padre solo ve el resultado agregado. Esto es exactamente cómo trabaja un desarrollador humano experimentado: no piensa en cada detalle al mismo tiempo. Entra en "modo investigación", luego en "modo implementación", etc. LangGraph es, en la práctica, una de las implementaciones más limpias de este enfoque. python from typing import TypedDict from langgraph.graph import StateGraph, START, END class AgentState TypedDict : task: str messages: list code: str status: str builder = StateGraph AgentState LangGraph permite meter un grafo completo como nodo de otro grafo. Eso es literalmente una Hierarchical State Machine. Hay dos patrones principales: El subgraph y el parent comparten claves del estado. El subgraph se agrega directamente como nodo builder.add node "investigar", investigar subgraph Cada subgraph tiene su propio schema y se hace una transformación explícita. python def call investigar state: AgentState : subgraph input = {"query": state "task" } result = investigar subgraph.invoke subgraph input return {"code": result "findings" } Además, LangGraph gestiona checkpoint namespaces por subgraph, lo que permite: Esto es extremadamente poderoso cuando pasamos de demos a sistemas reales. | Situación | Recomendación | |---|---| Prototipo/demo rápida | Loop simple suele alcanzar | Agente con pocas tools | FSM plana | Agente con modos claros | HSM subgraphs | Multi-agente / equipos | HSM + supervisor | Producción con observabilidad | State machine explícita | No hay que formalizar todo desde el día uno. Pero cuando el flujo empieza a volverse difícil de seguir, convertir el ciclo en una máquina de estados y eventualmente jerárquica suele ser el siguiente paso natural. Y aquí vuelve el punto del principio: si no tenés claros estos conceptos, es fácil que el modelo te proponga una HSM cuando en realidad necesitabas una FSM simple. O al revés. El ciclo Think Act Observe no es solo una metáfora. Es una máquina de estados. Las Hierarchical State Machines nos permiten escalar esa idea sin que el sistema se convierta en un laberinto de if s y prompts. Y frameworks como LangGraph nos dan las primitivas exactas para implementarlo de forma limpia: StateGraph + Subgraphs . Resumen: Un agente no es solo un modelo con tools. Es un modelo operando dentro de una máquina de estados que puede ser jerárquica . Entender esto cambia bastante la forma en que diseñamos, debuggeamos y operamos agentes.