
# Máquinas de estados

Las máquinas de estados y los flujos de trabajo resuelven problemas distintos.

Un flujo de trabajo responde a «¿qué tarea se ejecuta a continuación?». Una máquina de estados responde a «¿en qué estado se encuentra este elemento y qué eventos son válidos en este punto?». Esta diferencia importa cuando lo que está creando no es solo una secuencia de pasos, sino una entidad de larga duración que reacciona a entradas externas a lo largo del tiempo, como una sesión de agente, un hilo de chat, un ciclo de revisión, un ticket o un flujo de aprobación.

## Ejemplo rápido

```php
use Queuety\Enums\StateMachineStatus;
use Queuety\Queuety;

$machine_id = Queuety::machine( 'agent_session' )
    ->version( 'agent-session.v1' )
    ->state( 'awaiting_user' )
    ->on( 'user_message', 'planning' )
    ->state( 'planning' )
    ->action( PlanSessionAction::class )
    ->on( 'planned', 'awaiting_review' )
    ->state( 'awaiting_review' )
    ->on( 'approve', 'completed', ReviewApprovedGuard::class )
    ->on( 'reject', 'awaiting_user' )
    ->state( 'completed', StateMachineStatus::Completed )
    ->dispatch( [ 'thread_id' => 42 ] );

Queuety::machine_event(
    $machine_id,
    'user_message',
    [ 'message' => 'Find competitors for this product' ]
);

Queuety::machine_event(
    $machine_id,
    'approve',
    [ 'approved' => true, 'reviewer' => 'editor@example.com' ]
);
```

Esta máquina comienza en `awaiting_user`, pasa a `planning` cuando llega un mensaje del usuario, permite que la acción en cola emita `planned` y luego espera en `awaiting_review` hasta que una aprobación externa complete la sesión. Lo importante no es solo la sintaxis del código, sino que el ciclo de vida sea explícito, inspeccionable y orientado a eventos.

## Cómo se ejecuta una máquina

Cuando se envía una instancia de máquina, Queuety conserva el nombre del estado actual, la carga útil pública del estado, la versión y el hash de la definición, los eventos entrantes válidos para el estado actual y una cronología duradera de eventos.

Si el estado al que se entra tiene un `action()`, Queuety pone en cola un trabajo de entrada al estado. Esa acción puede limitarse a actualizar el estado público y dejar la máquina a la espera del siguiente evento, o puede emitir `_event` y, opcionalmente, `_event_payload` para activar de inmediato la siguiente transición. Si el estado no tiene ninguna acción ni un estado terminal, la máquina simplemente espera eventos externos enviados con `Queuety::machine_event()`.

## Cómo elegir entre flujos de trabajo y máquinas de estados

Use un flujo de trabajo cuando la ejecución se base fundamentalmente en pasos: obtener datos, esperar por cada tarea, sintetizar y terminar. Este modelo encaja bien cuando hay un inicio y un final claros, y la pregunta principal es qué tarea debe ejecutarse a continuación.

Use una máquina de estados cuando el comportamiento válido dependa de la fase actual del ciclo de vida. Es la opción más adecuada cuando los eventos pueden llegar en distinto orden, la entidad puede existir durante mucho tiempo o necesita inspeccionar explícitamente el ciclo de vida mediante estados como `awaiting_user`, `planning`, `running_agents`, `awaiting_review` y `completed`.

## Cómo encajan ambas opciones

Las dos primitivas funcionan mejor juntas que por separado. Una acción de estado puede enviar un flujo de trabajo cuando una transición requiere una ejecución más intensa, y un flujo de trabajo puede emitir un evento a una máquina cuando termina esa tarea. En la práctica, esto permite que la máquina de estados controle el ciclo de vida mientras los flujos de trabajo realizan las ejecuciones costosas o muy estructuradas.

## Estructura del constructor

`StateMachineBuilder` se mantiene deliberadamente pequeño. `initial()` y `state()` definen el grafo del ciclo de vida. `action()` vincula el trabajo en cola a un estado. `on()` declara qué eventos pueden llevar la máquina al siguiente estado. `on_queue()`, `with_priority()` y `max_attempts()` controlan cómo se ejecutan las acciones de estado, mientras que `version()` y `idempotency_key()` añaden metadatos de envío duraderos. `dispatch()` crea la instancia de la máquina.

Las acciones de estado también pueden exponer un método opcional `config()`, que usa las mismas claves de política de recursos que los pasos y controladores de flujos de trabajo. Esto permite mantener una transición de estado costosa dentro de un grupo de concurrencia compartido o asignarle un peso de coste mayor cuando una acción consume más presupuesto que un paso normal.

El modelo general de recursos se describe en [Gestión de recursos](https://queuety.inline0.dev/es/docs/features/resource-management).

## Contratos

Las acciones de entrada a un estado implementan `Queuety\Contracts\StateAction`:

```php
namespace Queuety\Contracts;

interface StateAction {
    public function handle( array $state, ?string $event = null, array $event_payload = [], array $payload = [] ): array|string;
}
```

`$payload` es la carga útil estructurada de la definición de la acción; está vacío cuando la acción se indica como un nombre de clase simple. Queuety crea acciones con `new $class()`, por lo que una clase de acción necesita un constructor sin argumentos obligatorios.

Las acciones de estado también pueden definir un método opcional `config()` con `concurrency_group`, `concurrency_limit` y `cost_units` cuando la acción de entrada en cola deba participar en la admisión de trabajadores, los presupuestos ponderados de colas o proveedores y otras políticas de recursos.

Las condiciones de transición implementan `Queuety\Contracts\StateGuard`:

```php
namespace Queuety\Contracts;

interface StateGuard {
    public function allows( array $state, array $event_payload, string $event, array $payload = [] ): bool;
}
```

## API de inspección

Use la fachada para inspeccionar las máquinas en ejecución:

```php
$status   = Queuety::machine_status( $machine_id );
$machines = Queuety::list_machines();
$events   = Queuety::machine_timeline( $machine_id );
$trace    = Queuety::machine_trace( $machine_id );
$state    = Queuety::machine_state_at( $machine_id, $event_id );
```

Las máquinas de estados no tienen comandos WP-CLI: `wp queuety workflow ...` solo cubre los flujos de trabajo. Use estas API PHP, por ejemplo mediante `wp eval`, para inspeccionar máquinas desde la línea de comandos.

Estas API exponen el nombre del estado actual, el estado del ciclo de vida, el estado público, los eventos disponibles, los metadatos de la definición, la cronología completa de transiciones y un paquete de trazas normalizado para las interfaces de depuración. Las filas de la lista de máquinas incluyen la versión y el hash de la definición, además de la clave de idempotencia, para que las pantallas de lista muestren la versión de origen y de ejecución sin cargar cada máquina por separado. El paquete de trazas incluye estados agrupados, eventos sin procesar, trabajos de acción correlacionados, registros, referencias a artefactos, referencias a fragmentos, entrada y salida del controlador, estado anterior y posterior, contexto, tiempos y errores estructurados.

## Sesiones de agente

Las máquinas de estados son especialmente útiles para sistemas de agentes que se comportan más como sesiones que como flujos de procesamiento. Una sesión que pasa por `awaiting_user`, `planning`, `running_agents`, `awaiting_review` y `completed` suele ser más fácil de entender como un ciclo de vida explícito que como una definición de flujo de trabajo muy larga con muchas esperas y retornos a pasos anteriores.

## Véase también

- [Neuron Máquina de estados de sesión](https://queuety.inline0.dev/es/docs/examples/neuron-session-state-machine)
- [Neuron Máquina de estados de memoria y revisión](https://queuety.inline0.dev/es/docs/examples/neuron-memory-review)
- [Orquestación de agentes](https://queuety.inline0.dev/es/docs/workflows/agent-orchestration)
- [Señales de flujo de trabajo](https://queuety.inline0.dev/es/docs/workflows/signals)
- [Dependencias de flujo de trabajo](https://queuety.inline0.dev/es/docs/workflows/dependencies)
- [Repeticiones](https://queuety.inline0.dev/es/docs/workflows/repeats)
- [Artefactos](https://queuety.inline0.dev/es/docs/features/artifacts)
- [PHP API](https://queuety.inline0.dev/es/docs/api)
