<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Xavier Gutiérrez</title>
    <description>The latest articles on DEV Community by Xavier Gutiérrez (@xvierd).</description>
    <link>https://dev.to/xvierd</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F256510%2Ff8961369-89be-452c-91f7-14a4d5031a0c.jpg</url>
      <title>DEV Community: Xavier Gutiérrez</title>
      <link>https://dev.to/xvierd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xvierd"/>
    <language>en</language>
    <item>
      <title>Agentes 101 - 02: El ciclo del agente como State Machine (y Hierarchical State Machines)</title>
      <dc:creator>Xavier Gutiérrez</dc:creator>
      <pubDate>Sun, 26 Jul 2026 15:09:16 +0000</pubDate>
      <link>https://dev.to/xvierd/agentes-101-02-el-ciclo-del-agente-como-state-machine-y-hierarchical-state-machines-5986</link>
      <guid>https://dev.to/xvierd/agentes-101-02-el-ciclo-del-agente-como-state-machine-y-hierarchical-state-machines-5986</guid>
      <description>&lt;p&gt;En el artículo anterior definimos un agente de forma práctica:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Un agente LLM es un modelo dentro de un &lt;strong&gt;ciclo&lt;/strong&gt; donde puede razonar, actuar, observar el resultado y decidir qué hacer después.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esa definición es correcta. Pero todavía es demasiado abstracta.&lt;/p&gt;

&lt;p&gt;Hoy mucha gente está construyendo agentes con &lt;strong&gt;vibe coding&lt;/strong&gt;. 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.&lt;/p&gt;

&lt;p&gt;El problema es que muchas veces se termina implementando algo sin entender los conceptos base.&lt;/p&gt;

&lt;p&gt;Y cuando no se entienden los conceptos, el modelo puede proponer soluciones más complejas de lo necesario. Por ejemplo, sugerirte una &lt;strong&gt;Hierarchical State Machine&lt;/strong&gt; cuando una &lt;strong&gt;Finite State Machine&lt;/strong&gt; simple habría sido más que suficiente (y capaz ni siquiera te das cuenta de que es una FSM o HSM)..&lt;/p&gt;

&lt;p&gt;Por eso este artículo.&lt;/p&gt;

&lt;p&gt;No para complicar las cosas, sino para tener claridad sobre qué estamos construyendo realmente.&lt;/p&gt;

&lt;p&gt;La pregunta central es:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Cómo modelamos el ciclo de un agente de forma explícita, controlable y escalable?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;La respuesta es: tratarlo como una &lt;strong&gt;máquina de estados&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  El ciclo Think Act Observe como máquina de estados
&lt;/h2&gt;

&lt;p&gt;Imaginemos el flujo más simple de un agente:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Recibe una tarea&lt;/li&gt;
&lt;li&gt;Razona sobre qué hacer&lt;/li&gt;
&lt;li&gt;Decide si necesita usar una herramienta&lt;/li&gt;
&lt;li&gt;Ejecuta la herramienta&lt;/li&gt;
&lt;li&gt;Observa el resultado&lt;/li&gt;
&lt;li&gt;Decide si terminó o si debe seguir&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ese flujo se puede modelar perfectamente como una &lt;strong&gt;Finite State Machine (FSM)&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Estado&lt;/th&gt;
&lt;th&gt;Descripción&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;'thinking'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;El modelo está razonando&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;'acting'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Está ejecutando una herramienta&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;'observing'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Está procesando el resultado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;'done'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Terminó la tarea&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;'error'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Algo falló&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Las transiciones dependen del resultado de cada paso.&lt;/p&gt;

&lt;p&gt;Eso es exactamente lo que hace un agente.&lt;/p&gt;




&lt;h2&gt;
  
  
  Una State Machine simple
&lt;/h2&gt;

&lt;p&gt;Aquí un ejemplo conceptual (pseudo-código):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Implementar CORS en API Gateway con CDK&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;last_observation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thinking&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;done&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thinking&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;decision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;think&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;needs_tool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;acting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;next_tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;done&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;final_answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt;

    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;acting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;run_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;next_tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;last_observation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;observing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;observing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# El modelo decide qué hacer con la observación
&lt;/span&gt;        &lt;span class="n"&gt;next_action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next_action&lt;/span&gt;  &lt;span class="c1"&gt;# puede ser "thinking", "done", "error"...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este patrón es el corazón de casi todos los frameworks de agentes.&lt;/p&gt;

&lt;p&gt;La diferencia está en qué tan explícito se hace el control del estado.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tools = acciones que cambian el estado
&lt;/h3&gt;

&lt;p&gt;Las herramientas no son un "extra".&lt;/p&gt;

&lt;p&gt;Son acciones que producen una observación y, por lo tanto, cambian el estado de la máquina.&lt;/p&gt;

&lt;p&gt;Cuando el agente llama a &lt;code&gt;search_docs&lt;/code&gt; o &lt;code&gt;run_tests&lt;/code&gt;, lo que realmente está haciendo es:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Salir del estado &lt;code&gt;thinking&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Entrar al estado &lt;code&gt;acting&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Ejecutar una acción&lt;/li&gt;
&lt;li&gt;Recibir una observación&lt;/li&gt;
&lt;li&gt;Actualizar el estado&lt;/li&gt;
&lt;li&gt;Decidir la siguiente transición&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Si pensamos las tools de esta forma, el diseño se vuelve mucho más claro:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Una tool bien diseñada tiene un contrato claro de entrada/salida.&lt;/strong&gt; El resultado de la tool debe poder interpretarse para decidir la siguiente transición.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;El manejo de errores de tools se convierte en transiciones hacia el estado error o hacia un estado de recuperación.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Cuando la máquina se complica: Hierarchical State Machines
&lt;/h2&gt;

&lt;p&gt;Una FSM plana funciona bien para agentes simples.&lt;/p&gt;

&lt;p&gt;Pero cuando el agente crece, empiezan a aparecer problemas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Demasiados estados&lt;/li&gt;
&lt;li&gt;Transiciones difíciles de seguir&lt;/li&gt;
&lt;li&gt;Lógica de "modo investigación" mezclada con "modo implementación"&lt;/li&gt;
&lt;li&gt;Dificultad para reutilizar partes del flujo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aquí es donde aparecen las &lt;strong&gt;Hierarchical State Machines (HSM)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;La idea es simple: &lt;strong&gt;un estado puede contener otra máquina de estados completa.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cada sub-máquina tiene su propio estado interno, pero el padre solo ve el resultado agregado.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;




&lt;h2&gt;
  
  
  Cómo lo implementa LangGraph
&lt;/h2&gt;

&lt;p&gt;LangGraph es, en la práctica, una de las implementaciones más limpias de este enfoque.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. StateGraph = la máquina de estados
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.graph&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;
    &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;El &lt;strong&gt;State&lt;/strong&gt; es el estado compartido.&lt;/li&gt;
&lt;li&gt;Los &lt;strong&gt;nodes&lt;/strong&gt; son las funciones que actualizan el estado.&lt;/li&gt;
&lt;li&gt;Las &lt;strong&gt;edges&lt;/strong&gt; (especialmente las condicionales) definen las transiciones.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Subgraphs = Hierarchical State Machines
&lt;/h3&gt;

&lt;p&gt;LangGraph permite meter un grafo completo como nodo de otro grafo.&lt;/p&gt;

&lt;p&gt;Eso es literalmente una Hierarchical State Machine.&lt;/p&gt;

&lt;p&gt;Hay dos patrones principales:&lt;/p&gt;

&lt;h4&gt;
  
  
  Patrón A - Shared State
&lt;/h4&gt;

&lt;p&gt;El subgraph y el parent comparten claves del estado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# El subgraph se agrega directamente como nodo
&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;investigar&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;investigar_subgraph&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Patrón B - Isolated State
&lt;/h4&gt;

&lt;p&gt;Cada subgraph tiene su propio schema y se hace una transformación explícita.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call_investigar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;subgraph_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;investigar_subgraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subgraph_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;findings&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Además, LangGraph gestiona checkpoint namespaces por subgraph, lo que permite:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Aislar el estado de cada sub-máquina&lt;/li&gt;
&lt;li&gt;Recuperar el estado después de fallos&lt;/li&gt;
&lt;li&gt;Hacer &lt;em&gt;human-in-the-loop&lt;/em&gt; a nivel de sub-proceso&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esto es extremadamente poderoso cuando pasamos de demos a sistemas reales.&lt;/p&gt;




&lt;h2&gt;
  
  
  ¿Cuándo vale la pena formalizarlo?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situación&lt;/th&gt;
&lt;th&gt;Recomendación&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Prototipo/demo rápida&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Loop simple suele alcanzar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agente con pocas tools&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;FSM plana&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agente con modos claros&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;HSM (subgraphs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-agente / equipos&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;HSM + supervisor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Producción con observabilidad&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;State machine explícita&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No hay que formalizar todo desde el día uno.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;El ciclo &lt;strong&gt;Think Act Observe&lt;/strong&gt; no es solo una metáfora.&lt;/p&gt;

&lt;p&gt;Es una máquina de estados.&lt;/p&gt;

&lt;p&gt;Las &lt;strong&gt;Hierarchical State Machines&lt;/strong&gt; nos permiten escalar esa idea sin que el sistema se convierta en un laberinto de &lt;code&gt;if&lt;/code&gt;s y prompts.&lt;/p&gt;

&lt;p&gt;Y frameworks como LangGraph nos dan las primitivas exactas para implementarlo de forma limpia: &lt;code&gt;StateGraph&lt;/code&gt; + &lt;code&gt;Subgraphs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Resumen:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Un agente no es solo un modelo con tools.&lt;br&gt;&lt;br&gt;
Es un modelo operando dentro de una máquina de estados (que puede ser jerárquica).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Entender esto cambia bastante la forma en que diseñamos, debuggeamos y operamos agentes.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>architecture</category>
      <category>llm</category>
    </item>
    <item>
      <title>Agentes 101 - 01</title>
      <dc:creator>Xavier Gutiérrez</dc:creator>
      <pubDate>Sat, 25 Apr 2026 19:32:24 +0000</pubDate>
      <link>https://dev.to/xvierd/agentes-101-01-3il3</link>
      <guid>https://dev.to/xvierd/agentes-101-01-3il3</guid>
      <description>&lt;h2&gt;
  
  
  ¿Qué es realmente un agente LLM?
&lt;/h2&gt;

&lt;p&gt;Llevo tiempo queriendo escribir sobre agentes. No porque el tema sea nuevo, sino porque cada vez que parece que empezamos a entenderlo, cambia el nivel de abstracción con el que se habla de él.&lt;/p&gt;

&lt;p&gt;Y ahí empieza buena parte del problema.&lt;/p&gt;

&lt;p&gt;Hoy una persona dice “agente” y se refiere a un sistema con tools, memoria, planificación y control de estado. Otra usa la misma palabra para hablar de un prompt bien diseñado dentro de un archivo &lt;code&gt;.md&lt;/code&gt;. Y otra simplemente la usa para describir cualquier flujo donde un modelo hace más de un paso.&lt;/p&gt;

&lt;p&gt;Mientras tanto, la adopción en empresas tampoco ocurre al mismo ritmo. Algunas organizaciones todavía están evaluando asistentes de código en grupos pequeños. Otras ya probaron varias herramientas, cambiaron de enfoque más de una vez y ahora están intentando separar qué fue entusiasmo, qué fue utilidad real y qué sí puede sostenerse en producción.&lt;/p&gt;

&lt;p&gt;Por eso, cuando en una conversación aparece la pregunta:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;¿Qué es un agente?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;casi nunca hay una sola respuesta.&lt;/p&gt;

&lt;p&gt;Y el problema no es que falten definiciones. El problema es que muchas definiciones son correctas, pero se quedan demasiado arriba y no siempre ayudan a entender qué está pasando en la práctica.&lt;/p&gt;




&lt;h2&gt;
  
  
  La respuesta corta
&lt;/h2&gt;

&lt;p&gt;Una definición razonable sería esta:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Un LLM común genera texto a partir de su entrenamiento.&lt;br&gt;&lt;br&gt;
Un agente LLM es ese mismo modelo dentro de un ciclo donde puede razonar, usar herramientas, recibir feedback y ajustar su siguiente acción.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dicho de otra forma:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LLM + tools + memory + planning = agente&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No está mal. De hecho, es una buena síntesis.&lt;/p&gt;

&lt;p&gt;Pero también es el tipo de respuesta que muchas personas escuchan, entienden de forma parcial y luego repiten sin terminar de visualizar qué significa realmente.&lt;/p&gt;

&lt;p&gt;Así que conviene detenerse un poco más.&lt;/p&gt;




&lt;h2&gt;
  
  
  Una definición más útil
&lt;/h2&gt;

&lt;p&gt;La forma que más me convence de explicarlo es esta:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Un agente LLM es un LLM dentro de un workflow iterativo donde puede razonar, actuar y usar el resultado de sus acciones para decidir qué hacer después.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ese matiz importa.&lt;/p&gt;

&lt;p&gt;Porque el centro de la idea no está solo en el modelo, sino en el &lt;strong&gt;ciclo&lt;/strong&gt; en el que ese modelo opera.&lt;/p&gt;

&lt;p&gt;No es magia.&lt;br&gt;&lt;br&gt;
No es una categoría mística de software.&lt;br&gt;&lt;br&gt;
Es un sistema con estructura.&lt;/p&gt;


&lt;h2&gt;
  
  
  Visual general
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fio0so5zb2t1vew18zbq7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fio0so5zb2t1vew18zbq7.png" alt="Agent Loop" width="800" height="1110"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  La analogía más simple: un desarrollador humano
&lt;/h2&gt;

&lt;p&gt;Una buena forma de aterrizarlo es compararlo con el trabajo cotidiano de un desarrollador.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Fase humana&lt;/th&gt;
&lt;th&gt;Equivalente del agente&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Recibe un requerimiento&lt;/td&gt;
&lt;td&gt;Recibe un prompt o una task&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Piensa cómo abordarlo&lt;/td&gt;
&lt;td&gt;Razona sobre el problema&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Busca documentación, prueba opciones, escribe código&lt;/td&gt;
&lt;td&gt;Usa tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ejecuta, valida y corrige&lt;/td&gt;
&lt;td&gt;Actúa sobre el entorno&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ve errores, resultados o confirmaciones&lt;/td&gt;
&lt;td&gt;Recibe feedback&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ajusta el enfoque&lt;/td&gt;
&lt;td&gt;Decide el siguiente paso&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Eso es lo que hace que la idea deje de sonar abstracta.&lt;/p&gt;

&lt;p&gt;Un agente no es más que un modelo participando en algo que se parece bastante a un ciclo real de trabajo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;analizar&lt;/li&gt;
&lt;li&gt;actuar&lt;/li&gt;
&lt;li&gt;observar&lt;/li&gt;
&lt;li&gt;corregir&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La diferencia es que, en lugar de hacerlo con navegador, terminal, editor y pruebas como lo haría una persona, lo hace a través de herramientas conectadas al sistema.&lt;/p&gt;


&lt;h2&gt;
  
  
  Entonces, ¿de dónde sale tanta confusión?
&lt;/h2&gt;

&lt;p&gt;De que hoy la palabra &lt;strong&gt;agente&lt;/strong&gt; se usa para hablar de cosas bastante distintas.&lt;/p&gt;

&lt;p&gt;Hay personas que dicen “creé un agente” y, cuando miras más de cerca, en realidad lo que construyeron fue un archivo &lt;code&gt;.md&lt;/code&gt; con instrucciones muy claras para que Claude Code, Cursor u otra herramienta se comporte de cierta manera.&lt;/p&gt;

&lt;p&gt;Y eso no está mal.&lt;/p&gt;

&lt;p&gt;De hecho, muchas veces ese archivo contiene una parte valiosa del diseño:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;el rol&lt;/li&gt;
&lt;li&gt;las reglas&lt;/li&gt;
&lt;li&gt;las restricciones&lt;/li&gt;
&lt;li&gt;el criterio de calidad&lt;/li&gt;
&lt;li&gt;la forma de decidir entre opciones&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;El problema aparece cuando esa pieza se confunde con el sistema completo.&lt;/p&gt;

&lt;p&gt;Un &lt;code&gt;.md&lt;/code&gt; puede definir comportamiento. Puede incluso capturar muy bien la intención del flujo. Pero, por sí solo, normalmente no resuelve aspectos fundamentales como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ejecución de herramientas&lt;/li&gt;
&lt;li&gt;control de estado&lt;/li&gt;
&lt;li&gt;manejo de errores&lt;/li&gt;
&lt;li&gt;límites operativos&lt;/li&gt;
&lt;li&gt;observabilidad&lt;/li&gt;
&lt;li&gt;validación&lt;/li&gt;
&lt;li&gt;integración con otros sistemas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por eso, más que decir “eso sí es un agente” o “eso no es un agente”, creo que la distinción más útil es esta:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Un archivo de instrucciones puede ser una parte importante del agente, pero no suele ser suficiente para representar todo el sistema.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esa diferencia parece pequeña, pero cambia mucho la conversación.&lt;/p&gt;


&lt;h2&gt;
  
  
  Veamos un ejemplo en código
&lt;/h2&gt;

&lt;p&gt;Para hacerlo más tangible, le pedí a ChatGPT que generara un ejemplo sencillo usando &lt;code&gt;strands-agents&lt;/code&gt;, el framework de AWS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;strands&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tool&lt;/span&gt;

&lt;span class="c1"&gt;# --- Tools (simuladas) ---
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;search_docs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CORS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use API Gateway integrationResponses to handle CORS in AWS CDK.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No results found.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_tests&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cors&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tests passed ✅&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tests failed ❌: missing CORS config&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Registrar tools
&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nc"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_docs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;search_docs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Search technical documentation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;run_tests&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;run_tests&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Run code tests&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# --- Agente ---
&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
You are an autonomous software engineer.
You follow a loop:
1. Think about the problem
2. Decide if you need a tool
3. Act using tools
4. Observe results
5. Iterate until the task is complete
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# --- Task ---
&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Implement CORS in AWS API Gateway using CDK and verify it works&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# --- Loop ---
&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;--- Step &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; ---&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Thought:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;thought&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Action:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Observation:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;last_observation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;

        &lt;span class="c1"&gt;# Simulación: el agente escribe código
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CORS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;const cors = true;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Final Answer:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Es un ejemplo simple, pero alcanza para mostrar el patrón.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lo importante no es el framework
&lt;/h2&gt;

&lt;p&gt;Más allá del framework, lo importante es el ciclo:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think → Act → Observe → Iterate&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Eso es lo que le da forma al comportamiento del agente.&lt;/p&gt;

&lt;p&gt;No importa demasiado si usas &lt;code&gt;strands-agents&lt;/code&gt;, LangGraph, AutoGen, OpenAI Agents SDK o una implementación propia. En casi todos los casos, la lógica de fondo se parece bastante:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;el modelo analiza el problema
&lt;/li&gt;
&lt;li&gt;decide si necesita una herramienta
&lt;/li&gt;
&lt;li&gt;ejecuta una acción
&lt;/li&gt;
&lt;li&gt;observa el resultado
&lt;/li&gt;
&lt;li&gt;ajusta el siguiente paso
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cuando lo miras así, el concepto deja de parecer misterioso.&lt;/p&gt;

&lt;p&gt;No estamos hablando de una inteligencia separada del resto del sistema. Estamos hablando de un modelo que participa en un flujo iterativo con capacidad de actuar sobre un entorno.&lt;/p&gt;




&lt;h2&gt;
  
  
  ¿Por qué extender LLMs con tools?
&lt;/h2&gt;

&lt;p&gt;Porque un LLM sin tools tiene límites muy claros.&lt;/p&gt;

&lt;p&gt;Una analogía útil es imaginar a un desarrollador trabajando en un archivo &lt;code&gt;.txt&lt;/code&gt;, sin internet, sin compilador y sin un entorno donde validar nada.&lt;/p&gt;

&lt;p&gt;Puede razonar, sí.&lt;/p&gt;

&lt;p&gt;Pero no puede:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;buscar información nueva&lt;/li&gt;
&lt;li&gt;verificar si lo que hizo funciona&lt;/li&gt;
&lt;li&gt;ejecutar código&lt;/li&gt;
&lt;li&gt;consultar el estado real del mundo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ese es el punto clave.&lt;/p&gt;

&lt;p&gt;Un modelo sin herramientas puede producir texto muy convincente, pero no tiene cómo contrastarlo con la realidad.&lt;/p&gt;




&lt;h2&gt;
  
  
  Visual: LLM sin tools vs con tools
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flkmok8p7bi01y4iwymih.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flkmok8p7bi01y4iwymih.png" alt="LLM Tools" width="800" height="1229"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Qué cambia cuando agregas tools
&lt;/h2&gt;

&lt;p&gt;Cuando conectas tools, el modelo puede dejar de operar únicamente sobre lo que recuerda y empezar a interactuar con información y sistemas externos.&lt;/p&gt;

&lt;p&gt;Por ejemplo, puede:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;buscar documentación&lt;/li&gt;
&lt;li&gt;consultar una base de conocimiento&lt;/li&gt;
&lt;li&gt;ejecutar código&lt;/li&gt;
&lt;li&gt;correr pruebas&lt;/li&gt;
&lt;li&gt;leer archivos&lt;/li&gt;
&lt;li&gt;consultar APIs&lt;/li&gt;
&lt;li&gt;validar una respuesta con datos reales&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ese cambio es mucho más importante de lo que parece.&lt;/p&gt;

&lt;p&gt;Porque el valor ya no está solo en que el modelo “sepa” algo, sino en que puede &lt;strong&gt;hacer algo&lt;/strong&gt;, observar lo que ocurrió y usar ese resultado para continuar.&lt;/p&gt;

&lt;p&gt;Ahí es donde aparece la parte realmente interesante del comportamiento agéntico.&lt;/p&gt;




&lt;h2&gt;
  
  
  La idea clave
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Un agente no es solamente un modelo.&lt;br&gt;&lt;br&gt;
Es un modelo dentro de un ciclo, conectado a herramientas y expuesto a feedback del entorno.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esa definición, para mí, es mucho más útil que cualquier explicación grandilocuente.&lt;/p&gt;

&lt;p&gt;Porque además ayuda a desmontar una confusión bastante común: pensar que el salto de “LLM” a “agente” es una cuestión de branding o de complejidad artificial.&lt;/p&gt;

&lt;p&gt;No lo es.&lt;/p&gt;

&lt;p&gt;Lo que cambia no es solo el nombre.&lt;br&gt;&lt;br&gt;
Lo que cambia es la arquitectura del problema.&lt;/p&gt;




&lt;h2&gt;
  
  
  Entonces, ¿un archivo &lt;code&gt;.md&lt;/code&gt; es un agente?
&lt;/h2&gt;

&lt;p&gt;Por sí solo, normalmente no.&lt;/p&gt;

&lt;p&gt;Puede ser una pieza excelente de diseño. Puede capturar reglas, intención, tono, restricciones, prioridades e incluso estrategias de decisión. Y en algunos casos, eso ya aporta muchísimo valor.&lt;/p&gt;

&lt;p&gt;Pero cuando hablamos de un agente funcionando como sistema, suele hacer falta bastante más:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;un runtime que ejecute acciones&lt;/li&gt;
&lt;li&gt;herramientas reales&lt;/li&gt;
&lt;li&gt;estado&lt;/li&gt;
&lt;li&gt;validación&lt;/li&gt;
&lt;li&gt;manejo de errores&lt;/li&gt;
&lt;li&gt;observabilidad&lt;/li&gt;
&lt;li&gt;integración con otros componentes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por eso, más que oponer “prompt” contra “agente”, creo que conviene pensar en capas.&lt;/p&gt;

&lt;p&gt;Un &lt;code&gt;.md&lt;/code&gt; puede ser la capa de comportamiento.&lt;br&gt;&lt;br&gt;
El agente completo incluye además la capa de ejecución, control y operación.&lt;/p&gt;




&lt;h2&gt;
  
  
  Llevar esto a producción cambia por completo la conversación
&lt;/h2&gt;

&lt;p&gt;Aquí es donde muchas demos dejan de ser suficientes.&lt;/p&gt;

&lt;p&gt;En una prueba local, casi todo puede verse ordenado:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;el modelo recibe una instrucción&lt;/li&gt;
&lt;li&gt;llama una tool&lt;/li&gt;
&lt;li&gt;obtiene algo útil&lt;/li&gt;
&lt;li&gt;devuelve una respuesta razonable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pero producción introduce otro tipo de preguntas.&lt;/p&gt;

&lt;p&gt;No preguntas sobre la idea.&lt;br&gt;&lt;br&gt;
Preguntas sobre el sistema.&lt;/p&gt;

&lt;p&gt;Por ejemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;¿qué ocurre si una tool falla?&lt;/li&gt;
&lt;li&gt;¿cómo evitas loops innecesarios?&lt;/li&gt;
&lt;li&gt;¿cómo limitas costo y latencia?&lt;/li&gt;
&lt;li&gt;¿cómo registras las decisiones que tomó el agente?&lt;/li&gt;
&lt;li&gt;¿cómo auditas lo que hizo?&lt;/li&gt;
&lt;li&gt;¿cómo validas que una acción sea segura antes de ejecutarla?&lt;/li&gt;
&lt;li&gt;¿cómo recuperas el estado si el flujo se interrumpe?&lt;/li&gt;
&lt;li&gt;¿cómo haces retries sin duplicar efectos?&lt;/li&gt;
&lt;li&gt;¿dónde incorporas aprobación humana?&lt;/li&gt;
&lt;li&gt;¿cómo pruebas algo cuyo comportamiento depende de contexto, tools y feedback?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Y ahí se vuelve evidente algo importante:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;construir una demo con sabor a agente es relativamente fácil; construir un sistema confiable es otra cosa.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Por eso, cuando alguien pregunta si un agente es “solo un prompt con tools”, mi respuesta tiende a ser: a veces eso alcanza para una demo útil, pero no para describir todo lo que implica operarlo bien.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Más que decir que estamos en un momento extraño, diría que estamos en una etapa de ajuste.&lt;/p&gt;

&lt;p&gt;Todavía hay equipos que apenas están empezando a explorar asistentes de código. Otros ya pasaron por varias herramientas, frameworks y experimentos con agentes. Y muchos están descubriendo, quizá por primera vez, que bajo una misma palabra se mezclan ideas que conviene separar.&lt;/p&gt;

&lt;p&gt;Por eso la pregunta sigue apareciendo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;¿Qué es realmente un agente?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mi respuesta, hoy, sería esta:&lt;/p&gt;

&lt;p&gt;Un agente no es magia.&lt;br&gt;&lt;br&gt;
No es solamente un prompt.&lt;br&gt;&lt;br&gt;
No es simplemente un &lt;code&gt;.md&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Y tampoco es cualquier flujo con varias llamadas a un modelo.&lt;/p&gt;

&lt;p&gt;Un agente es un sistema donde un modelo puede:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;razonar&lt;/li&gt;
&lt;li&gt;actuar&lt;/li&gt;
&lt;li&gt;observar resultados&lt;/li&gt;
&lt;li&gt;y decidir qué hacer después en función de ese feedback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Entender eso no resuelve todo, pero sí limpia bastante el terreno.&lt;/p&gt;

&lt;p&gt;Y en un momento donde casi todo el mundo usa la palabra “agente” para algo distinto, tener una definición más concreta ya es un muy buen comienzo.&lt;/p&gt;




</description>
      <category>ai</category>
      <category>agents</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
