# Agentes 101 - 02: El ciclo del agente como State Machine (y Hierarchical State Machines)

> Source: <https://dev.to/xvierd/agentes-101-02-el-ciclo-del-agente-como-state-machine-y-hierarchical-state-machines-5986>
> Published: 2026-07-26 15:09:16+00:00

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.
