Skip links
Diagrama conceptual del agent loop de IA agéntica con las fases perception, reasoning, action y observation

IA Agéntica: arquitectura, agent loop y patrones de diseño

Los sistemas de IA agéntica no son chatbots mejorados. Son arquitecturas en las que un modelo de lenguaje toma decisiones en bucle, invoca herramientas externas, gestiona estado y persiste memoria entre turnos para completar objetivos complejos sin supervisión humana en cada paso. El salto conceptual es sustantivo: un chatbot responde; un agente de IA actúa, observa el resultado de su acción y decide el siguiente movimiento.

Esta guía cubre la arquitectura completa de la IA agéntica: el agent loop canónico, los cuatro componentes de un agente (LLM, tools, memoria, planner), los tres patrones de diseño dominantes en producción (ReAct, Plan-and-Execute, Reflexion) y los sistemas multi-agent. Si estás desarrollando agentes de IA para empresas o evaluando si la arquitectura agéntica encaja en tu stack, este es el recurso técnico de referencia en castellano. Incluye cinco bloques de código Python ejecutables y referencias a los papers originales.

Este post está dirigido a AI engineers, devs senior y arquitectos de sistemas. Si estás empezando con Python o nunca has hecho function calling con un LLM, lee antes la introducción al ecosistema de agentes de IA; aquí asumimos que conoces la API de OpenAI o Anthropic, async Python y el concepto de token context window. No es un post de divulgación: cada sección profundiza en decisiones de diseño con trade-offs reales.

Tabla de contenidos

  1. ¿Qué es IA agéntica y por qué no es un chatbot?
  2. El agent loop: perception → reasoning → action → observation
  3. Anatomía de un agente: LLM + tools + memoria + planner
  4. Patrón ReAct (Reason + Act): el más usado en producción
  5. Patrón Plan-and-Execute: planificación explícita
  6. Patrón Reflexion: auto-crítica y mejora iterativa
  7. Multi-agent systems: orquestador, swarm, supervisor
  8. Memoria: corto plazo, largo plazo, episódica, semántica
  9. Construir un agente ReAct desde cero (código)
  10. IA agéntica en producción: observabilidad, errores, costes
  11. Frameworks: LangGraph vs OpenAI Agents SDK vs CrewAI
  12. Preguntas frecuentes sobre IA agéntica
  13. Conclusión

¿Qué es IA agéntica y por qué no es un chatbot?

La IA agéntica es el paradigma en el que un modelo de lenguaje grande (LLM) actúa como motor de razonamiento dentro de un bucle autónomo capaz de percibir entradas, tomar decisiones, ejecutar acciones sobre herramientas externas y observar los resultados para decidir el siguiente paso, todo ello sin que un humano intervenga en cada iteración. El término agentic viene de agency: la capacidad de un sistema de actuar por cuenta propia en persecución de un objetivo.

Diferencias fundamentales frente a un chatbot

Un chatbot clásico opera en modo request-response: el usuario manda un mensaje, el LLM genera una respuesta, fin. El contexto puede acumularse, pero el sistema nunca toma iniciativa, no ejecuta código, no llama a APIs y no persiste estado más allá de la ventana de conversación. La interacción es stateless entre sesiones por diseño. Un agente, en cambio, mantiene un estado interno que evoluciona con cada ciclo del loop, puede ejecutar acciones con efectos secundarios en sistemas externos (bases de datos, APIs REST, navegadores web, sistemas de ficheros) y es capaz de replantear su plan cuando una acción falla o devuelve un resultado inesperado.

Qué hace autónomo a un agente

La autonomía en sistemas agénticos tiene tres dimensiones técnicas que conviene distinguir con precisión. La primera es la autonomía de acción: el agente puede invocar tools sin que el humano apruebe cada llamada. La segunda es la autonomía de planificación: el agente genera y revisa su propio plan de trabajo, no sigue un flujo fijo programado. La tercera es la autonomía de recuperación: cuando un tool call devuelve un error o un resultado inconsistente con el objetivo, el agente es capaz de reformular su estrategia. Estas tres dimensiones son lo que separa un agente de un workflow de automatización tradicional como Make o Zapier, donde el grafo de ejecución es determinista y está hardcodeado por el diseñador.

El espectro de autonomía

Conviene no ver la agenticidad como un binario sino como un espectro. En el extremo más bajo tienes un LLM con function calling puntual, donde el modelo llama a una sola herramienta y devuelve control al humano. En el extremo más alto tienes agentes fully autonomous capaces de ejecutar decenas de steps con mínima supervisión, como los sistemas de ingeniería de software autónoma (SWE-Agent, Devin). La mayoría de las implementaciones empresariales en 2026 operan en el rango semi-autónomo: loops de 3-10 steps con checkpoints humanos en decisiones irreversibles (enviar emails, modificar bases de datos de producción, realizar pagos). Entender dónde situar tu sistema en ese espectro es la primera decisión de arquitectura.

Por qué la IA agéntica importa ahora

Tres factores convergentes explican el salto de los últimos 18 meses. Primero, los LLMs de frontera (GPT-4o, Claude 3.5 Sonnet, Gemini 1.5 Pro) tienen capacidad de razonamiento suficiente para gestionar planes de varios pasos con coherencia. Segundo, la ventana de contexto ha crecido hasta 200K tokens en Anthropic y 1M en Gemini, permitiendo al agente procesar documentos completos sin perder el hilo. Tercero, el ecosistema de frameworks (LangGraph, OpenAI Agents SDK, CrewAI) ha madurado hasta ofrecer abstracciones production-ready con observabilidad integrada. El resultado es que tareas que antes requerían pipelines complejos de n8n o Zapier se pueden resolver hoy con un agente de 100 líneas de Python.

El agent loop: perception → reasoning → action → observation

El agent loop es el núcleo de toda arquitectura agéntica. Es el ciclo iterativo que el sistema ejecuta hasta que el agente determina que el objetivo ha sido alcanzado o que no puede progresar más. Entender cada fase del loop con precisión es indispensable antes de escribir una sola línea de código agéntico.

Las cuatro fases del loop

Perception es la fase en que el agente recibe el estado actual del entorno. Esto incluye el mensaje del usuario, los resultados de tool calls anteriores, el contenido de la memoria recuperada y cualquier evento externo (webhooks, timers). El agente no tiene acceso al mundo exterior salvo lo que le llega en esta fase: toda la percepción es mediada por el sistema. En implementaciones concretas, la percepción se construye ensamblando el system prompt con el historial de mensajes y los resultados de las observaciones previas, todo concatenado en la ventana de contexto del LLM.

Reasoning es la fase en que el LLM procesa la percepción y genera una decisión. Dependiendo del patrón de diseño, este razonamiento puede ser implícito (el modelo elige directamente un tool call) o explícito (el modelo genera primero un bloque de pensamiento en texto libre antes de decidir la acción, como ocurre en ReAct o con el parámetro thinking de Claude 3.5). El razonamiento explícito mejora la coherencia en cadenas largas porque el modelo puede trabajar el problema antes de comprometerse con una acción.

Action es la ejecución de la decisión tomada en reasoning. Las acciones toman dos formas: tool calls (llamadas a funciones externas: search, code interpreter, browser, base de datos) o final answer (el agente decide que tiene la información suficiente y genera la respuesta para el usuario). Los tool calls son asincrónicos en la mayoría de implementaciones modernas: el agente puede lanzar varios en paralelo si no hay dependencias entre ellos, reduciendo la latencia total del loop.

Observation es la recepción del resultado de la acción. El resultado del tool call (el JSON devuelto por una API, el stdout de un intérprete de código, el HTML de una página scrapeada) se incorpora al contexto del agente como un mensaje de rol tool o function. Esta observación pasa a formar parte de la percepción del siguiente ciclo. El bucle continúa hasta que se dispara la condición de salida: el agente genera una final answer, se supera el número máximo de pasos configurado, o se produce un error irrecuperable.

Condiciones de terminación y límites de seguridad

Un loop sin control de terminación es un agente que puede ejecutarse indefinidamente, consumir miles de tokens y generar efectos secundarios no deseados. Toda implementación de producción necesita al menos tres guardarraíles. Primero, un max_iterations configurable (típicamente 10-25 para tareas de complejidad media). Segundo, un timeout global en segundos para el loop completo. Tercero, una política de error handling que distinga errores recuperables (un tool devuelve 429 rate limit → reintentar con backoff) de errores terminales (el tool devuelve un error de autenticación → abortar y reportar). Sin estos tres elementos, el agente no es apto para producción.

Paralelismo en el loop

Los LLMs modernos con function calling permiten emitir múltiples tool calls en un único turno de reasoning. Cuando el agente necesita buscar en tres fuentes distintas antes de redactar una respuesta, puede lanzar las tres búsquedas en paralelo, reduciendo la latencia del loop de 3x a 1x. LangGraph implementa esto nativamente mediante nodos paralelos. El OpenAI Responses API y la Anthropic Tool Use API también soportan parallel tool calls en la misma respuesta del modelo. Aprovechar este paralelismo es crítico en agentes con alta densidad de tool calls.

Anatomía de un agente: LLM + tools + memoria + planner

Un agente de IA es la composición de cuatro componentes que interactúan entre sí durante el loop. Ninguno de los cuatro es prescindible en una arquitectura completa, aunque en implementaciones sencillas algunos pueden ser muy básicos. Definir con exactitud la responsabilidad de cada componente evita bugs arquitectónicos que son difíciles de depurar una vez el sistema está en producción.

LLM: el motor de razonamiento

El LLM es el único componente del agente que genera texto: toma el estado del contexto (percepción) y produce bien un tool call bien una respuesta final. La elección del modelo tiene consecuencias directas sobre la calidad del razonamiento, la ventana de contexto disponible y el coste por loop. En 2026 los modelos más usados en agentes de producción son GPT-4o (coste-calidad equilibrado, función calling robusta), Claude 3.5 Sonnet (mejor razonamiento en tareas largas, thinking nativo) y Gemini 1.5 Pro (1M token context, útil para agentes con documentos masivos). La elección debe hacerse evaluando el task type del agente, no el benchmark genérico del modelo.

Tools: los actuadores del agente

Las tools son las funciones que el agente puede invocar para interactuar con el mundo exterior. Cada tool tiene un esquema JSON (nombre, descripción, parámetros con tipos y descripción) que el LLM recibe en el system prompt o en el campo tools de la API. La descripción de cada tool es crítica: el LLM la usa para decidir cuándo invocar esa tool y con qué argumentos. Una descripción pobre produce tool calls incorrectos. Los tipos de tools más comunes son: search (web, vector store, SQL), code execution (Python sandbox), browser (Playwright/Puppeteer headless), file system (leer/escribir ficheros), API connectors (REST calls a sistemas de terceros) y human-in-the-loop (solicitar input humano en un checkpoint). Para integraciones con fuentes de datos externas, el Model Context Protocol — puedes leer la guía técnica de MCP — ofrece un estándar abierto que evita escribir conectores ad-hoc para cada tool.

Memoria: el estado persistente

La memoria del agente es lo que le permite mantener coherencia entre sesiones y aprender de interacciones pasadas. La sección dedicada a memoria profundiza en los cuatro tipos (corto plazo, largo plazo, episódica, semántica). En términos arquitectónicos, la memoria es la capa que media entre el loop actual y el estado histórico: extrae información relevante, la convierte en texto o embeddings y la inyecta en la percepción del agente en el momento adecuado. Una mala gestión de la memoria es la causa número uno de loops incoherentes en agentes de producción.

Planner: la estrategia de alto nivel

El planner es el componente que decide cómo descomponer un objetivo complejo en subpasos ejecutables. En el patrón ReAct, el planner es implícito: el propio LLM decide el siguiente paso en cada iteración. En el patrón Plan-and-Execute, el planner es explícito: existe un módulo separado (que puede ser otro LLM con un system prompt de planificación) que genera el plan completo al inicio y un executor que lo lleva a cabo. La elección entre planner implícito y explícito tiene implicaciones sobre la previsibilidad del agente (un plan explícito es más auditable) y sobre su flexibilidad (un planner implícito puede adaptarse a sorpresas en mitad del loop).

Patrón ReAct (Reason + Act): el más usado en producción

El patrón ReAct (Reasoning + Acting) fue formalizado en el paper de Yao et al. publicado en 2022 en arXiv (ReAct: Synergizing Reasoning and Acting in Language Models). Es el patrón dominante en producción porque equilibra simplicidad de implementación con calidad de razonamiento.

Cómo funciona ReAct

En ReAct, cada iteración del loop sigue la secuencia Thought → Action → Observation explicitada en texto. El LLM genera primero un Thought: un bloque de razonamiento en lenguaje natural donde el modelo verbaliza su análisis del estado actual y decide el siguiente paso. Luego genera una Action: la invocación de una tool específica con los argumentos necesarios. El sistema ejecuta la action y devuelve la Observation: el resultado crudo de la tool. Este trío se repite hasta que el Thought del modelo es «ya tengo suficiente información para responder» y genera la respuesta final sin invocar ninguna tool. La clave de ReAct es que el reasoning es legible: puedes auditar en logs el razonamiento paso a paso, lo cual es invaluable para debugging.

Por qué ReAct supera al prompting simple en tareas complejas

El paper de Yao et al. demostró que ReAct supera consistentemente al chain-of-thought puro (razonamiento sin acciones) y al acting puro (acciones sin razonamiento explícito) en benchmarks como HotpotQA, FEVER y AlfWorld. La razón es que el Thought actúa como un espacio de trabajo donde el modelo puede verificar su comprensión antes de comprometerse con una acción costosa (en latencia y tokens). Los modelos modernos con extended thinking (Claude 3.5 thinking: "enabled") aplican una variante de ReAct donde el bloque de reasoning es interno al modelo y no se expone en el output, lo que reduce tokens de output pero sacrifica la trazabilidad.

Limitaciones de ReAct

ReAct tiene dos limitaciones conocidas. La primera es la deriva del plan: en tareas largas (más de 10 steps), el modelo puede perder coherencia entre el objetivo original y las actions que toma en los últimos ciclos, porque el reasoning de cada ciclo solo tiene visibilidad local. La segunda es la irreversibilidad de acciones: si el agente ejecuta una acción con efectos secundarios (enviar un email, modificar un registro) antes de tener la información completa, no puede deshacerla. Para ambos casos, Plan-and-Execute es una alternativa más robusta.

Patrón Plan-and-Execute: planificación explícita

El patrón Plan-and-Execute separa en dos módulos distintos la planificación y la ejecución. El planner recibe el objetivo del usuario y genera un plan estructurado (típicamente una lista ordenada de subobjetivos) antes de que el agente ejecute ninguna acción. Luego el executor recorre el plan paso a paso, invocando tools y reportando resultados al planner, que puede revisar y ajustar el plan si un step falla o devuelve información que cambia la estrategia.

Cuándo usar Plan-and-Execute sobre ReAct

Plan-and-Execute es la elección correcta cuando el objetivo es suficientemente complejo como para requerir una estrategia de alto nivel antes de empezar a actuar. Los casos de uso más claros son: investigación profunda (el agente necesita visitar múltiples fuentes, cruzar información y redactar un informe estructurado), ingeniería de software autónoma (el agente necesita analizar un codebase, planificar los cambios, implementarlos y testearlos), y procesos de negocio multi-step (el agente coordina acciones en varios sistemas: CRM, email, facturación). En todos estos casos, un plan explícito reduce la deriva del objetivo que afecta a ReAct en loops largos.

El planner como LLM separado

La implementación más robusta de Plan-and-Execute usa dos LLMs distintos con system prompts especializados: el planner con un prompt orientado a descomposición de tareas y pensamiento estructurado, y el executor con un prompt orientado a ejecución táctica y manejo de errores. Esto permite usar un modelo más potente (y caro) para la planificación —que ocurre una sola vez— y un modelo más rápido y económico para la ejecución —que ocurre en cada step. Es una optimización de coste significativa en agentes de alta frecuencia. Para implementaciones con LangGraph, el artículo sobre agentes con estado en LangGraph explica cómo modelar el planner y el executor como nodos distintos en un grafo con estado compartido.

Patrón Reflexion: auto-crítica y mejora iterativa

El patrón Reflexion fue presentado por Shinn et al. en 2023 en el paper Reflexion: Language Agents with Verbal Reinforcement Learning. La intuición central es simple: un agente que reflexiona sobre sus errores pasados comete menos errores futuros, sin necesidad de fine-tuning del modelo base.

Arquitectura de Reflexion

Reflexion añade al loop estándar un tercer módulo: el reflector. Después de que el agente completa una tarea (o falla al completarla), el reflector analiza la traza del loop (el histórico de Thought/Action/Observation) y genera una reflexión verbal: un resumen de qué salió mal, qué asunciones resultaron incorrectas y qué haría diferente en el próximo intento. Esta reflexión se almacena en la memoria episódica del agente y se inyecta en el system prompt de la siguiente ejecución. En el benchmark HumanEval de generación de código, el paper reporta que Reflexion alcanza un 91% de precisión, frente al 80% de un agente ReAct sin reflexión.

Reflexion y memory management

La reflexión verbal solo es útil si el agente puede recuperarla en el momento oportuno. Si las reflexiones se acumulan sin gestión, saturan el contexto. La implementación práctica limita el número de reflexiones almacenadas (tipicamente las N más recientes) o usa un vector store para recuperar por similitud semántica las reflexiones más relevantes para la tarea actual. Este patrón conecta directamente con la arquitectura de RAG aplicada a la memoria del agente: la implementación de retrieval augmented generation que ya conoces para documentos externos es exactamente el mismo mecanismo aplicado a la memoria del propio agente. Para dominar este componente de memoria semántica, la guía sobre context engineering explica cómo estructurar lo que entra en el contexto del LLM para maximizar la coherencia del razonamiento.

Multi-agent systems: orquestador, swarm, supervisor

Cuando la complejidad de la tarea supera lo que un único agente puede manejar con coherencia, la solución es un sistema multi-agent: varios agentes especializados que coordinan su trabajo para completar el objetivo. Los sistemas multi-agent son el estado del arte en 2026 para tareas de alta complejidad como investigación científica autónoma, generación de código de aplicaciones completas y gestión de procesos de negocio end-to-end. El primer paso para diseñar un sistema de agentes de IA para empresas en producción es elegir la topología multi-agent correcta.

Topología orquestador-worker

La topología más común en producción es el orquestador-worker. Un agente orquestador recibe el objetivo de alto nivel, lo descompone en subtareas y las delega a agentes worker especializados (un worker para búsqueda web, otro para análisis de código, otro para redacción). Los workers devuelven sus resultados al orquestador, que los integra y decide el siguiente paso. Esta topología es jerárquica y centralizada: el orquestador tiene visibilidad completa del estado del sistema. Es la arquitectura recomendada por Anthropic en su guía sobre agentes efectivos para la mayoría de casos de uso empresariales por su previsibilidad y facilidad de debugging.

Topología supervisor

En la topología supervisor, el supervisor es un LLM que actúa como router: recibe cada output de los workers y decide qué worker debe actuar a continuación, incluyendo la posibilidad de devolver control al humano o de terminar el loop. A diferencia del orquestador, el supervisor no genera el plan completo de antemano: toma decisiones de routing en cada step basándose en el estado actual. LangGraph implementa esta topología nativamente: el supervisor es un nodo condicional cuyo output determina qué arista del grafo se recorre. La guía sobre LangGraph y agentes con estado cubre la implementación detallada de este patrón.

Topología swarm (descentralizada)

En la topología swarm, no hay orquestador central. Cada agente en el swarm tiene acceso al estado compartido y puede tomar el control cuando su especialización es relevante para el estado actual. El agente activo puede pasar el control a otro agente mediante un mecanismo de handoff. Esta topología es más flexible y resiliente a fallos de un nodo individual, pero es significativamente más difícil de depurar porque el flujo de control no es predecible. OpenAI Swarm (ahora parte del OpenAI Agents SDK) fue la primera implementación pública de esta topología. Es adecuada para tareas donde los dominios de especialización están bien definidos y los handoffs son semánticamente claros.

Comunicación entre agentes

Los agentes en un sistema multi-agent se comunican a través de mensajes estructurados. En implementaciones basadas en LangGraph, el estado compartido del grafo actúa como el canal de comunicación: cada agente lee y escribe en campos tipados del estado. En implementaciones más acopladas, el orquestador llama directamente a los workers como si fueran tools (el worker es una function que el orquestador invoca con argumentos). La segunda aproximación es más sencilla de implementar pero menos escalable: añadir workers es tan fácil como añadir tools. Ambas aproximaciones se integran con los patrones de routing de LangChain. Para despliegues en cloud con workers distribuidos, los agentes cloud sobre Bedrock y Vertex ofrecen infraestructura gestionada para este tipo de topologías.

Memoria: corto plazo, largo plazo, episódica, semántica

La taxonomía de la memoria en sistemas agénticos sigue el trabajo de Lilian Weng (LLM Powered Autonomous Agents, 2023), que establece cuatro tipos de memoria análogos a la psicología cognitiva: in-context, external, episodic y semantic. Entender la diferencia entre ellos es fundamental para decidir qué almacenar, dónde y cómo recuperarlo.

Memoria de corto plazo (in-context)

La memoria de corto plazo es el historial de mensajes del loop actual: todo lo que está en la ventana de contexto del LLM en el turno presente. Es la forma de memoria más inmediata y la única que el modelo puede acceder sin ningún mecanismo de retrieval. Su limitación es el tamaño de la context window: con ventanas de 128K o 200K tokens, un loop de muchos steps puede acercarse al límite, especialmente si las observaciones de los tool calls son verbosas (HTML de páginas web, output de intérpretes de código). Las estrategias de compresión de contexto (summarización de mensajes antiguos, truncation inteligente) son la solución estándar. El área de context engineering cubre estas técnicas en detalle.

Memoria de largo plazo (external)

La memoria de largo plazo es el estado que persiste entre sesiones. Puede ser tan simple como un fichero JSON con el historial de conversaciones de un usuario, o tan complejo como una base de datos relacional con el estado de proyectos en curso. La decisión de qué persistir depende del caso de uso: para un agente de IA para ventas, el historial de interacciones con cada lead es esencial; para un agente de investigación one-shot, la persistencia entre sesiones puede no ser necesaria. El acceso a la memoria de largo plazo se implementa mediante tool calls: el agente invoca explícitamente un tool de escritura o lectura de memoria cuando lo necesita, en lugar de que la memoria se inyecte automáticamente.

Memoria episódica

La memoria episódica almacena el registro de experiencias concretas: qué hizo el agente en situaciones pasadas y cuál fue el resultado. Es el tipo de memoria que usa el patrón Reflexion. En la práctica, la memoria episódica se implementa como una colección de registros estructurados (tarea + traza del loop + resultado + reflexión) almacenados en una base de datos y recuperables por similitud con la tarea actual. El ciclo de evaluación de estas memorias —¿fue exitoso el outcome? ¿qué score le asignamos?— conecta con el campo de evaluación de agentes con LLM as judge, donde otro LLM actúa como evaluador de la calidad del output.

Memoria semántica (vector store)

La memoria semántica es el conocimiento factual del dominio, almacenado como embeddings en un vector store y recuperado por similitud semántica. Es el componente de RAG aplicado a la memoria del agente: en lugar de recuperar chunks de documentos externos, recupera fragmentos de conocimiento que el agente ha acumulado. La implementación requiere un pipeline de ingestión (chunking + embedding + upsert al vector store), un pipeline de retrieval (embed query + búsqueda kNN) y una capa de reranking opcional. Para profundizar en la elección y configuración del vector store, la comparativa de bases de datos vectoriales evalúa Chroma, Pinecone, Weaviate y pgvector en escenarios reales.

Construir un agente ReAct desde cero (código)

Los siguientes cinco bloques de código son ejecutables con las dependencias indicadas en cada caso. El orden es progresivo: del loop más simple sin framework al sistema multi-agent completo con LangGraph.

1. Agent loop minimalista (sin framework)

El primer ejemplo muestra el agent loop puro en ~30 líneas: sin LangChain, sin LangGraph, solo la API de OpenAI y Python estándar. El objetivo es que quede visible la estructura del loop antes de introducir abstracciones.

import json
import openai

client = openai.OpenAI()

TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "search_web",
            "description": "Busca información actualizada en la web.",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "Query de búsqueda"}
                },
                "required": ["query"],
            },
        },
    }
]

def search_web(query: str) -> str:
    # En producción: llamada real a Tavily, Serper o Exa
    return f"[Resultado simulado para: {query}]"

def run_agent(user_message: str, max_iterations: int = 10) -> str:
    messages = [{"role": "user", "content": user_message}]

    for step in range(max_iterations):
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
            tools=TOOLS,
            tool_choice="auto",
        )
        msg = response.choices[0].message
        messages.append(msg)

        if not msg.tool_calls:
            # El agente decidió responder sin tool call → fin del loop
            return msg.content

        # Ejecutar cada tool call y añadir la observación
        for tc in msg.tool_calls:
            fn_name = tc.function.name
            fn_args = json.loads(tc.function.arguments)
            result = search_web(**fn_args)  # dispatcher real usaría un dict de callables
            messages.append({
                "role": "tool",
                "tool_call_id": tc.id,
                "content": result,
            })

    return "Max iterations reached without a final answer."

if __name__ == "__main__":
    answer = run_agent("¿Cuál es el precio actual del cobre en los mercados internacionales?")
    print(answer)

2. Agente ReAct completo con LangGraph

El segundo bloque implementa el patrón ReAct con LangGraph: el grafo define el nodo de reasoning (el LLM) y el nodo de tools (el executor de tool calls), con una arista condicional que decide si continuar el loop o terminar.

from typing import Annotated, TypedDict
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, BaseMessage
from langchain_core.tools import tool
from langgraph.graph import StateGraph, END
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode

# --- Definición del estado ---
class AgentState(TypedDict):
    messages: Annotated[list[BaseMessage], add_messages]

# --- Tools ---
@tool
def search(query: str) -> str:
    """Realiza una búsqueda web y devuelve los resultados más relevantes."""
    # En producción: integrar TavilySearchResults o similar
    return f"Resultados para '{query}': [datos simulados]"

@tool
def calculator(expression: str) -> str:
    """Evalúa una expresión matemática de forma segura."""
    try:
        result = eval(expression, {"__builtins__": {}})
        return str(result)
    except Exception as e:
        return f"Error: {e}"

tools = [search, calculator]
tool_node = ToolNode(tools)

# --- Modelo ---
model = ChatOpenAI(model="gpt-4o", temperature=0).bind_tools(tools)

# --- Nodos del grafo ---
def call_model(state: AgentState) -> AgentState:
    response = model.invoke(state["messages"])
    return {"messages": [response]}

def should_continue(state: AgentState) -> str:
    """Decide si continuar el loop o terminar."""
    last_message = state["messages"][-1]
    if last_message.tool_calls:
        return "tools"
    return END

# --- Construcción del grafo ---
workflow = StateGraph(AgentState)
workflow.add_node("agent", call_model)
workflow.add_node("tools", tool_node)
workflow.set_entry_point("agent")
workflow.add_conditional_edges("agent", should_continue, {"tools": "tools", END: END})
workflow.add_edge("tools", "agent")

graph = workflow.compile()

# --- Ejecución ---
result = graph.invoke({"messages": [HumanMessage(content="¿Cuánto es el 15% de 2.847?")]})
print(result["messages"][-1].content)

3. Patrón Plan-and-Execute

El tercer bloque implementa Plan-and-Execute con dos LLMs distintos: el planner genera el plan estructurado y el executor lo lleva a cabo step a step, reportando resultados al planner para posibles revisiones.

import json
from openai import OpenAI

client = OpenAI()

PLANNER_PROMPT = """Eres un planificador experto. Dado un objetivo, genera un plan
estructurado como lista JSON de pasos. Cada paso tiene: {"step": int, "task": str, "tool": str, "args": dict}.
Responde SOLO con el JSON, sin texto adicional."""

EXECUTOR_PROMPT = """Eres un executor. Recibirás un step del plan y el contexto acumulado.
Ejecuta el step, reporta el resultado y si detectas que el plan debe ajustarse, indica 'REPLAN: '."""

def plan(objective: str) -> list[dict]:
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": PLANNER_PROMPT},
            {"role": "user", "content": f"Objetivo: {objective}"},
        ],
        response_format={"type": "json_object"},
    )
    return json.loads(response.choices[0].message.content).get("steps", [])

def execute_step(step: dict, context: str) -> str:
    response = client.chat.completions.create(
        model="gpt-4o-mini",  # Modelo más rápido y económico para ejecución
        messages=[
            {"role": "system", "content": EXECUTOR_PROMPT},
            {"role": "user", "content": f"Step: {json.dumps(step)}\nContexto: {context}"},
        ],
    )
    return response.choices[0].message.content

def run_plan_and_execute(objective: str) -> str:
    plan_steps = plan(objective)
    context = ""
    for step in plan_steps:
        result = execute_step(step, context)
        context += f"\nStep {step['step']} resultado: {result}"
        if "REPLAN:" in result:
            # Solicitar replanificación con el contexto actualizado
            plan_steps = plan(f"{objective}\nContexto hasta ahora: {context}")
    return context

if __name__ == "__main__":
    output = run_plan_and_execute(
        "Investiga los tres principales frameworks de agentes IA en Python y compara su popularidad en GitHub."
    )
    print(output)

4. Sistema multi-agent con supervisor en LangGraph

El cuarto bloque implementa la topología supervisor: un nodo supervisor que hace routing entre tres workers especializados (investigador, analista, redactor).

from typing import Literal, TypedDict, Annotated
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, BaseMessage
from langgraph.graph import StateGraph, END
from langgraph.graph.message import add_messages

# --- Estado compartido ---
class TeamState(TypedDict):
    messages: Annotated[list[BaseMessage], add_messages]
    next_worker: str

WORKERS = ["researcher", "analyst", "writer", "FINISH"]

supervisor_model = ChatOpenAI(model="gpt-4o", temperature=0)
worker_model = ChatOpenAI(model="gpt-4o-mini", temperature=0)

SUPERVISOR_PROMPT = f"""Eres el supervisor de un equipo de agentes.
Dado el estado de la tarea, decide qué agente debe actuar a continuación.
Workers disponibles: {WORKERS}.
Responde SOLO con el nombre del worker siguiente o 'FINISH' si la tarea está completa."""

def supervisor_node(state: TeamState) -> TeamState:
    response = supervisor_model.invoke(
        [{"role": "system", "content": SUPERVISOR_PROMPT}] + state["messages"]
    )
    next_worker = response.content.strip()
    return {"next_worker": next_worker, "messages": [response]}

def make_worker_node(name: str, system_prompt: str):
    def worker_node(state: TeamState) -> TeamState:
        response = worker_model.invoke(
            [{"role": "system", "content": system_prompt}] + state["messages"]
        )
        response.name = name
        return {"messages": [response]}
    return worker_node

researcher = make_worker_node("researcher", "Eres un investigador experto. Busca y sintetiza información relevante.")
analyst = make_worker_node("analyst", "Eres un analista. Evalúa la información y extrae insights clave.")
writer = make_worker_node("writer", "Eres un redactor técnico. Redacta el output final de forma clara y estructurada.")

def route_supervisor(state: TeamState) -> str:
    return state["next_worker"]

# --- Construcción del grafo ---
workflow = StateGraph(TeamState)
workflow.add_node("supervisor", supervisor_node)
workflow.add_node("researcher", researcher)
workflow.add_node("analyst", analyst)
workflow.add_node("writer", writer)

workflow.set_entry_point("supervisor")
workflow.add_conditional_edges(
    "supervisor",
    route_supervisor,
    {"researcher": "researcher", "analyst": "analyst", "writer": "writer", "FINISH": END},
)
for worker in ["researcher", "analyst", "writer"]:
    workflow.add_edge(worker, "supervisor")

graph = workflow.compile()

result = graph.invoke({
    "messages": [HumanMessage(content="Analiza el estado actual de los frameworks de IA agéntica en 2026.")],
    "next_worker": "",
})
print(result["messages"][-1].content)

5. Memoria semántica con vector store

El quinto bloque implementa la capa de memoria semántica: almacenar interacciones pasadas como embeddings y recuperarlas por similitud para inyectarlas en el contexto del agente en la siguiente sesión.

from openai import OpenAI
import chromadb
import uuid

client = OpenAI()
chroma = chromadb.Client()
collection = chroma.get_or_create_collection(name="agent_memory")

def embed(text: str) -> list[float]:
    response = client.embeddings.create(model="text-embedding-3-small", input=text)
    return response.data[0].embedding

def store_memory(user_id: str, interaction: str, metadata: dict = None) -> None:
    """Almacena una interacción en la memoria semántica del agente."""
    embedding = embed(interaction)
    collection.add(
        ids=[str(uuid.uuid4())],
        embeddings=[embedding],
        documents=[interaction],
        metadatas=[{"user_id": user_id, **(metadata or {})}],
    )

def retrieve_memories(user_id: str, query: str, n_results: int = 3) -> list[str]:
    """Recupera las memorias más relevantes para la query actual."""
    query_embedding = embed(query)
    results = collection.query(
        query_embeddings=[query_embedding],
        n_results=n_results,
        where={"user_id": user_id},
    )
    return results["documents"][0] if results["documents"] else []

def build_system_prompt_with_memory(user_id: str, current_query: str) -> str:
    memories = retrieve_memories(user_id, current_query)
    memory_block = "\n".join(f"- {m}" for m in memories) if memories else "Sin interacciones previas relevantes."
    return f"""Eres un asistente con memoria semántica.
Interacciones relevantes del usuario (recuperadas por similitud):
{memory_block}

Usa este contexto para personalizar tu respuesta."""

# --- Uso ---
user_id = "user_42"

# Almacenar interacciones previas
store_memory(user_id, "El usuario preguntó sobre costes de Pinecone vs Chroma y prefiere soluciones open source.")
store_memory(user_id, "El usuario trabaja con Python 3.11 y tiene experiencia con FastAPI.")

# En la próxima sesión, recuperar contexto relevante
system_prompt = build_system_prompt_with_memory(user_id, "¿Qué vector store me recomiendas para mi agente?")
print(system_prompt)

IA agéntica en producción: observabilidad, errores, costes

Construir un agente que funciona en local y construir un agente que funciona en producción son dos tareas fundamentalmente distintas. La diferencia está en tres áreas: observabilidad (saber qué hace el agente en cada momento), manejo de errores (qué ocurre cuando una tool falla) y gestión de costes (un loop con 20 steps y 100K tokens puede costar más de lo que el caso de uso justifica).

Observabilidad: tracing de agent loops

La herramienta de facto para tracing de agentes en 2026 es LangSmith (para stacks LangChain/LangGraph) o Langfuse (agnóstico de framework, open source). Ambas capturan cada turno del loop —input al LLM, tool calls emitidos, observaciones recibidas, output final— y los almacenan en un dashboard navegable. Sin tracing, debuggear un agente en producción es trabajar a ciegas: el loop puede fallar en el step 8 de 12 y sin traza es imposible saber si el fallo fue en el reasoning del LLM, en la ejecución del tool call o en la interpretación de la observación. La evaluación sistemática de estas trazas es el dominio del LLM as judge para evaluación de agentes.

Manejo de errores y circuit breakers

Un agente de producción necesita una estrategia explícita para cada clase de error posible. Los errores de tool calls se clasifican en tres categorías. Los errores transitorios (rate limits 429, timeouts de red) se manejan con retry exponential backoff, generalmente 3 intentos con delays de 1s, 2s, 4s. Los errores de validación (la tool espera un argumento en formato ISO 8601 y el LLM envía otra cosa) se manejan inyectando el error como observación y dejando al agente reformular el tool call. Los errores terminales (autenticación fallida, recurso inexistente) deben interrumpir el loop inmediatamente y reportar al humano sin continuar ejecutando steps que asumen el resultado de la tool fallida.

Optimización de costes en loops largos

El coste de un agente es la suma de los tokens de entrada y salida de cada turno del loop multiplicado por el precio del modelo. En un agente con 15 steps que usa GPT-4o, el acumulado puede llegar a 500K-1M tokens de entrada (porque el historial de mensajes crece con cada turno). Las estrategias de optimización más efectivas son: context compression (resumir los mensajes más antiguos del historial antes de pasarlos al LLM), model downgrade (usar un modelo más económico como GPT-4o-mini para los steps de ejecución táctica y reservar GPT-4o para el planning), y caching (las APIs de OpenAI y Anthropic ofrecen prompt caching con descuento del 50-75% para prefijos de prompt estáticos como el system prompt). Para el agente de voz con IA en llamadas telefónicas, el control de costes es especialmente crítico dado el volumen de tokens de transcripción.

Frameworks: LangGraph vs OpenAI Agents SDK vs CrewAI

La elección de framework para construir un agente no es trivial: cada uno tiene trade-offs significativos en expresividad, complejidad de setup, observabilidad nativa y ecosistema. La tabla siguiente compara los tres frameworks dominantes en producción en 2026.

CriterioLangGraphOpenAI Agents SDKCrewAI
Modelo de programaciónGrafo de estados tipado (StateGraph)Agentes con handoffs, Python-firstCrews + Tasks + Roles declarativos
Soporte multi-agentNativo (subgrafos, supervisor)Nativo (swarm, handoffs)Nativo (crews jerárquicas)
ObservabilidadLangSmith integradoOpenAI Dashboard + trace APIBásica; integra con LangSmith
Modelos soportadosCualquier LangChain LLMSolo OpenAI (gpt-* y o-* models)Cualquier LangChain LLM
Curva de aprendizajeAlta (grafos + estado tipado)Media (Python OOP)Baja (YAML/declarativo)
Control de flujoMáximo (aristas condicionales arbitrarias)Medio (handoff context)Bajo (proceso definido en crew)
Caso de uso idealAgentes complejos, producción empresarialAgentes sobre ecosistema OpenAIPrototipos rápidos, casos de uso claros

LangGraph es el framework más potente para agentes de producción complejos: el modelo de grafo con estado tipado permite expresar cualquier topología de agent loop y multi-agent con control total sobre el flujo. La contrapartida es la curva de aprendizaje. Si tu stack está completamente dentro del ecosistema OpenAI, el OpenAI Agents SDK ofrece una DX más sencilla con handoffs y swarm out-of-the-box. Para el framework LangChain en modo chains (sin LangGraph), la flexibilidad es menor pero el ecosistema de integraciones es el más amplio disponible. Para despliegues en infraestructura cloud gestionada, considera los agentes cloud en AWS Bedrock o Google Vertex.

Preguntas frecuentes sobre IA agéntica

¿Cuál es la diferencia entre IA agéntica y un chatbot con function calling?

La diferencia es el grado de autonomía y la capacidad de iteración. Un chatbot con function calling puede invocar una tool en un turno y devolver el resultado al usuario. Un agente agéntico ejecuta un bucle de múltiples iteraciones de forma autónoma: invoca tools, observa los resultados, razona sobre ellos y decide el siguiente step sin intervención humana en cada paso. La capacidad de replantear el plan cuando un step falla o devuelve información inesperada es lo que diferencia un agente de un chatbot con function calling puntual. En términos de arquitectura, la diferencia es el loop y el state management entre iteraciones.

¿Cuántos steps debería tener un agent loop en producción?

El número óptimo de steps depende de la complejidad de la tarea y del modelo usado, pero como regla práctica la mayoría de agentes de producción se configuran con un max_iterations entre 10 y 25. Por debajo de 10 el agente puede no tener suficiente espacio para completar tareas complejas. Por encima de 25 el coste de tokens se dispara y la probabilidad de deriva del objetivo aumenta. Si tu agente necesita consistentemente más de 25 steps para completar una tarea, es una señal de que la tarea es demasiado grande para un único agente y debería descomponerse en un sistema multi-agent con subagentes especializados.

¿Qué modelo LLM debo usar para mis agentes?

La elección del modelo depende de tres factores: la complejidad del razonamiento requerido, el volumen de llamadas y el presupuesto. Para tareas que requieren razonamiento complejo y planes de múltiples steps, GPT-4o o Claude 3.5 Sonnet son la elección dominante en 2026. Para steps de ejecución táctica dentro de un agente Plan-and-Execute, GPT-4o-mini o Claude 3 Haiku son suficientes y significativamente más económicos. Para agentes que necesitan procesar documentos de cientos de páginas en una sola llamada, Gemini 1.5 Pro con su ventana de 1M tokens es la única opción viable. La evaluación sistemática de la calidad del modelo en tu caso de uso específico —mediante el patrón de LLM as judge— siempre supera a los benchmarks genéricos.

¿Cómo evito que un agente ejecute acciones irreversibles por error?

El patrón estándar es implementar checkpoints humanos (human-in-the-loop) antes de cualquier acción con efectos secundarios irreversibles. En LangGraph esto se implementa como un nodo de interrupt que pausa el grafo y espera aprobación humana antes de continuar. Las acciones irreversibles más comunes en entornos empresariales son: enviar emails, modificar o eliminar registros en bases de datos de producción, realizar transacciones financieras y publicar contenido en canales públicos. El diseño defensivo también incluye implementar un modo dry-run para cada tool, que simula la acción y devuelve el resultado esperado sin ejecutarla realmente, útil para testing y validación antes del despliegue.

¿Cuáles son los principales riesgos de seguridad en sistemas agénticos?

El riesgo más crítico específico de los sistemas agénticos es el prompt injection: si el agente procesa contenido externo (documentos, resultados de búsqueda, emails) que contiene instrucciones maliciosas diseñadas para modificar el comportamiento del agente, un atacante puede secuestrar el loop. Las mitigaciones incluyen: sanitizar el contenido externo antes de inyectarlo en el contexto, usar roles de mensaje distintos para distinguir contenido de usuario vs contenido de herramientas vs instrucciones del sistema, y limitar los permisos de las tools al mínimo necesario (principio de mínimo privilegio). Los agentes con acceso a internet, código execution y sistemas de producción son especialmente críticos desde el punto de vista de seguridad.

¿ReAct, Plan-and-Execute o Reflexion: cuál usar en mi proyecto?

La heurística de selección es directa. Usa ReAct si tu tarea tiene una estructura razonablemente lineal, el número de steps es moderado (menor de 10) y la trazabilidad del reasoning step a step tiene valor en sí misma. Usa Plan-and-Execute cuando la tarea requiere una estrategia de alto nivel antes de actuar, el horizonte de planificación es largo o las acciones son costosas de deshacer. Usa Reflexion cuando el agente realizará la misma clase de tarea repetidamente y necesitas que mejore entre ejecuciones sin fine-tuning. En muchos casos reales, la solución óptima combina patrones: Plan-and-Execute para la estructura global + Reflexion para mejorar la calidad del planner con el tiempo.

Conclusión

La IA agéntica no es una tendencia pasajera: es el modelo de programación que define cómo se construyen los sistemas de IA de próxima generación. El agent loop, los patrones ReAct, Plan-and-Execute y Reflexion, y las topologías multi-agent no son conceptos académicos: son herramientas de producción que equipos de ingeniería están usando hoy para automatizar procesos que antes requerían intervención humana constante.

Dominar esta arquitectura requiere entender cada capa: el LLM como motor de razonamiento, las tools como actuadores, la memoria como capa de persistencia y el planner como estratega. Los frameworks maduros —LangGraph, OpenAI Agents SDK— abstraen la complejidad de implementar estas capas desde cero, pero los principios del loop son agnósticos de framework y seguirán siendo válidos independientemente de cómo evolucione el ecosistema en los próximos meses.

En Baigency trabajamos con estas arquitecturas en implementaciones reales para empresas: desde agentes de IA para ventas hasta agentes de voz con IA para atención telefónica. Si estás evaluando qué arquitectura agéntica encaja mejor en tu caso de uso, podemos ayudarte a diseñarla antes de escribir la primera línea de código. Contacta con el equipo y cuéntanos el problema.