Arquitectura de ejecución y contexto
El desarrollo de agentes de inteligencia artificial modernos con LangGraph marca una evolución significativa respecto a las cadenas lineales tradicionales. En lugar de un flujo unidireccional, trabajamos con sistemas cíclicos donde la persistencia y la gestión de la información se vuelven aspectos centrales del diseño.
Para garantizar la robustez y escalabilidad de un agente, es fundamental distinguir entre tres componentes que operan durante el ciclo de vida de una ejecución: el Estado, la Configuración y el Contexto. Confundir estos elementos suele llevar a códigos acoplados y difíciles de testear, donde la lógica de negocio se mezcla con detalles de infraestructura.
El Runtime actúa como el entorno de ejecución efímero que orquesta estas piezas. Cada vez que invocamos al agente, se instancia este entorno para inyectar tanto el estado mutable (lo que el agente "piensa") como el contexto inmutable (las herramientas que el agente "usa") en cada nodo del grafo.
A continuación, desglosaremos las diferencias técnicas entre estos componentes y cómo se implementan en la práctica.
State vs. Config vs. Context
Cuando invocamos un agente pasamos una serie de parámetros:
agent.invoke:input(AgentState):- aquí van los
messages, es el input en la invocación, es el estado mutable que cambia en cada paso del grafo, normalmente incluye la lista "messages" pero se puede extender para que tenga otros atributos extra si creamos una clase que herede de AgentState.
- aquí van los
config(RunnableConfig):- Es un diccionario genérico (sin tipos definidos).
- Contiene: tags, metadata, callbacks, run_name, max_concurrency, recursion_limit, configurable, run_id, thread_id
context(ContextT)- contexto estático, aquí solemos agregar datos que sirvan por ejemplo para interactuar con la memoria long-term, como por ejemplo un user_id para identificar al usuario que está ejecutando esa invocación. Es estructurado y tipado (puedes usar Pydantic o dataclasses). Está diseñado para dependencias de negocio (API clients, User preferences, Servicios), no para configuración del framework.
Si optamos por extender el state creando una clase que herede de AgentState, y también optamos por configurar un Context entonces debemos indicarle esos nuevos esquemas al agente en su creación:
create_agent:state_schema(por defecto AgentState pero se puede extender, si lo extendemos indicamos aquí el esquema)context_schema(si hemos creado Context le indicamos aquí el esquema)store(base de datos long term memory)checkpointer(base de datos short-term memory)
Runtime
En LangGraph, cuando ejecutas create_agent (o compilas un grafo), no estás creando una instancia en ejecución. Estás creando un plano (Blueprint) o una fábrica.
Por tanto el proceso sería así, cuando llamas a agent.invoke(...), el grafo compilado actúa como una fábrica:
- Toma tu
StoreyCheckpointer(definidos globalmente encreate_agent). - Toma el
ContextyConfig(de esta petición específica, si los hay). - Fabrica un objeto
Runtimeefímero para esa interacción. - Pasa ese
Runtimehacia abajo a las tools, para que puedan acceder al context, store. - Cuando termina la ejecución, ese
Runtimese destruye.
Por tanto, en cada ejecución del agente se construye un Runtime que viaja a los middleware y tools.
Ejemplo de middleware:
@dataclass
class Context:
user_name: str
@before_model
def log_before_model(state: AgentState, runtime: Runtime[Context]) -> dict | None:
print(f"Processing request for user: {runtime.context.user_name}")
return None
agent = create_agent(
model="gpt-5-nano",
tools=[...],
middleware=[log_before_model],
context_schema=Context
)
agent.invoke(
{"messages": [{"role": "user", "content": "What's my name?"}]},
context=Context(user_name="John Smith")
)
En este ejemplo vemos cómo se crea un Context, y ese context es accesible en el Runtime que entra en un middleware.
ToolRuntime
En el caso de las herramientas (Tools) LangGraph genera un Runtime llamado ToolRuntime que contiene state, context, config, stream_writer, tool_call_id, and store. Por lo que es una manera de unificar toda la información del agente en un solo objeto ToolRuntime que entra en la herramienta y así podemos usar para acceder a la información.
Ejemplo:
from langchain.tools import tool, ToolRuntime
@tool
def get_user_email(runtime: ToolRuntime[ContextSchema]) -> str:
"""Retrieve user information based on user ID."""
# simulate fetching user info from a database
email = get_user_email_from_db(runtime.context.user_name)
return email
Fuentes y referencias
Documentación oficial y recursos externos para profundizar en LangChain
Documentación oficial de LangChain
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, LangChain es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de LangChain
Explora más contenido relacionado con LangChain y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Comprender la diferencia entre Estado, Configuración y Contexto en Runtime, acceder a runtime desde herramientas mediante ToolRuntime, trabajar con context_schema para inyectar dependencias, y entender cómo Runtime orquesta el ciclo de vida del agente.
Cursos que incluyen esta lección
Esta lección forma parte de los siguientes cursos estructurados con rutas de aprendizaje