Inicio / Artículos

Notas prácticas: Aprender LangGraph: Un viaje a través de los agentes y las pizarras negras

Guía paso a paso operativa de las notas prácticas: Aprender LangGraph: Un viaje a través de los agentes, las pizarras: contratos, verificaciones y espacios para código integrable para los equipos que implementan este patrón.

Editor: REACTAPP.TOP14 min de lectura3277 palabras

Fuentes: Learning LangGraph : A Journey Through Agents, Blackboards, and Bottlenecks

Las notas siguientes reconstruyen un camino práctico para abordar “Aprender LangGraph: Un viaje a través de agentes, pizarras y cuellos de botella”. Se da énfasis en los contratos, las verificaciones y los marcadores de posición para código reutilizable, en lugar de en un enfoque motivacional. Al trabajar en la sección de Resumen, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de un fallo parcial. Esa lista de verificación garantiza que los cambios posteriores en el código sean transparentes. Registre los tiempos de ejecución y el costo en tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando se pasa de entornos de demostración a entornos compartidos.

Paso 1: El agente mínimo

Paso 1: El agente mínimo funciona mejor cuando se trata como una superficie medible. Capture una transcripción exitosa, un caso de fallo y la nota de reversión antes de ampliar el alcance. Mantenga la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de secretos y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin tener que leer todo el grafo. Mantenga el estado del grafo plano y tipado. Los bloques anidados ocultan qué nodo escribió qué campo y provocan interrupciones en la continuación del proceso.

from langchain.agents import create_agent          # langchain 1.x (NOT langgraph.prebuilt)
from langchain.tools import tool
from langchain_anthropic import ChatAnthropic

# 1. Model
llm = ChatAnthropic(model="claude-haiku-4-5", max_tokens=1024)

# 2. Tool — a plain function + @tool.
#    - type hints (drug_name: str) become the input schema
#    - the docstring is what the LLM reads to decide WHEN to call it
#    The model only "sees" the signature + docstring, so write the docstring
#    like an API description.
@tool
def get_drug_targets(drug_name: str) -> str:
    """Return the protein targets for a given drug name."""
    return "EGFR, BRAF"   # real data-source call goes here

# 3. System prompt — a plain string
SYSTEM_PROMPT = "You are a research assistant. Use the tools to gather evidence."

# 4. Build the agent
agent = create_agent(model=llm, tools=[get_drug_targets], system_prompt=SYSTEM_PROMPT)

# 5. Run it — pass in {"messages": [...]}, get the full message list back
result = agent.invoke({"messages": [{"role": "user", "content": "What does metformin target?"}]})
print(result["messages"][-1].content)   # last message = final answer
@tool
def calculator(expression: str) -> str:
    """Evaluate a basic arithmetic expression like '2 + 2 * 3'."""
    return str(eval(expression))   # fine for learning; never eval untrusted input in prod

Paso 2: Hacer que dos agentes se comuniquen

Paso 2: Lograr que dos agentes hablen funciona mejor cuando se trata como una superficie medible. Capture una transcripción exitosa, un caso de fallo y la nota de reversión antes de ampliar el alcance. Documente tanto el camino óptimo como el de recuperación juntos. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores. Mantenga el estado del grafo simple y tipado; los bloques anidados ocultan qué nodo escribió qué campo y provocan interrupciones en la continuación.

Opción 1: Mensajes

Opción 1: Messages funciona mejor cuando se trata como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Prefiera unidades pequeñas y verificables en lugar de scripts extensos. Cuando falla un paso, el fallo debe apuntar a una sola responsabilidad y no a un proceso complicado. Mantenga el estado del grafo simple y tipado; los bloques anidados ocultan qué nodo escribió qué campo y causan interrupciones en la continuación del proceso. Opción 1: Messages funciona mejor cuando se trata como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Registre los tiempos y el costo de tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando el proceso pasa de la versión de demostración a entornos compartidos.

Opción 2: Blackboard

Para la Opción 2: Blackboard, defina las entradas, el responsable de la etapa y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar la etapa desde un punto de control conocido sin tener que adivinar el estado oculto. Mantenga la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de datos secretos y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin necesidad de leer todo el sistema. Coloque la aprobación humana en las conexiones que generan gastos o modifican datos de producción. La conexión en tiempo de compilación no equivale a la completitud del proceso empresarial.

Paso 3: Extraer datos introducidos por un agente

Para el Paso 3: Obtener datos ingresados de un agente, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Documente tanto la ruta óptima como la ruta de recuperación. Las reintentos, los controles humanos y el manejo de correos no entregados forman parte del producto, no son mejoras posteriores. Incluya la aprobación humana en aquellos procesos que generen gastos o modifiquen datos de producción. La conexión en tiempo de compilación no equivale a la completitud del negocio.

from pydantic import BaseModel, Field

class ResearchOutput(BaseModel):
    attraction: str = Field(description="2 sentences about the attraction")
    city: str = Field(description="1 sentence about the city it is in")

agent = create_agent(
    model=llm,
    tools=[attraction_info, city_info],
    system_prompt=SYSTEM_PROMPT,
    response_format=ResearchOutput,   # <- agent emits this typed object
)
result = agent.invoke({"messages": [...]})
out = result["structured_response"]   # a ResearchOutput instance
out.attraction   # str
out.city         # str
def research_node(state):
    out = research(state["topic"])           # ResearchOutput
    return {"research": out.attraction, "city": out.city}

El acoplamiento que esto crea

Para el acoplamiento que esto genera, defina las entradas, el responsable de la tarea y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar la tarea desde un punto de control conocido sin tener que adivinar el estado oculto. Prefiera unidades pequeñas y verificables en lugar de scripts extensos. Cuando una tarea falla, el error debe indicar una única responsabilidad y no un proceso complicado. Incluya la aprobación humana en aquellas acciones que implican gastos o modificaciones en datos de producción. La conexión en tiempo de compilación no equivale a la completitud del proceso empresarial. Para el acoplamiento que esto genera, defina las entradas, el responsable de la tarea y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar la tarea desde un punto de control conocido sin tener que adivinar el estado oculto. Registre los tiempos de ejecución y el costo de tokens o consultas junto con los resultados funcionales. La visibilidad temprana del costo evita facturas inesperadas cuando el proceso pasa de entornos de demostración a entornos compartidos.

SYSTEM_PROMPT = "...\n" + "\n".join(f"- {t.name}: {t.description}" for t in TOOLS)

Cuatro variantes, un dial cada una

Al trabajar con las cuatro variantes, una dial cada una, anote primero el contrato: los datos requeridos, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación ayuda a mantener honestas las futuras modificaciones en el código. Guarde la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de datos secretos y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin tener que leer todo el sistema. Haga un punto de control después de los pasos costosos. La función de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador intente nuevamente un nodo posterior.

Paso 4: ¿Por qué es tan lento esto? — y qué realmente lo soluciona

Al trabajar en el Paso 4: ¿Por qué es tan lento esto? — y qué realmente lo soluciona?, anote primero el contrato: entradas requeridas, señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Documente junto con ello el camino óptimo y el camino de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores. Haga un punto de control después de los pasos costosos. Resume no debe volver a facturar la misma llamada al LLM cuando un operador vuelve a intentar un nodo posterior.

def _crowd_score_sync(attraction: str) -> str:   # plain blocking function
    total = 0
    for i in range(60_000_000):
        total += i
    return f"... {total % 100} ..."

@tool
async def crowd_score(attraction: str) -> str:
    return await asyncio.to_thread(_crowd_score_sync, attraction)

Por qué el agente ReAct sigue siendo lento sin importar nada

Al analizar por qué el agente ReAct sigue siendo lento sin importar las circunstancias, primero escribe el contrato: los inputs requeridos, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación garantiza que los cambios posteriores en el código sean transparentes. Prefiere unidades pequeñas y verificables a scripts extensos. Cuando un paso falla, el fallo debe apuntar a una única responsabilidad y no a un proceso complicado. Haz un punto de control después de los pasos costosos. La función de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador intenta nuevamente un nodo posterior. Al analizar por qué el agente ReAct sigue siendo lento sin importar las circunstancias, primero escribe el contrato: los inputs requeridos, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación garantiza que los cambios posteriores en el código sean transparentes. Registra los tiempos y el costo en tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando el proceso pasa de la versión de demostración a entornos compartidos.

Paso 5: Ejecutar pipelines completos de forma concurrente

Paso 5: Ejecutar pipelines completos de forma concurrente funciona mejor cuando se trata como una superficie medible. Capture una transcripción de referencia, un caso de fallo y la nota de reversión antes de ampliar el alcance. Mantenga la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de secretos y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin tener que leer todo el grafo. Mantenga el estado del grafo plano y tipado. Los bloques anidados ocultan qué nodo escribió qué campo y provocan interrupciones en la continuación de la ejecución.

Paso 6: Hacer que el caché funcione realmente

Paso 6: Para que el caché funcione realmente bien, es mejor tratarlo como un elemento medible. Capture una transcripción exitosa, un caso de fallo y la nota de reversión antes de ampliar el alcance. Documente tanto el camino óptimo como el de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores. Mantenga el estado del gráfico simple y tipado; los bloques anidados ocultan qué nodo escribió qué campo y provocan interrupciones en la continuación del proceso.

system_prompt = "You are a travel research agent..."   # string: no keys

content = [{                                            # dict: has keys
    "type": "text",
    "text": "You are a travel research agent...",
    "cache_control": {"type": "ephemeral"},            # <- attaches here
}]
from langchain_anthropic.middleware import AnthropicPromptCachingMiddleware

agent = create_agent(
    model=llm, tools=[...], system_prompt=SYSTEM_PROMPT,  # plain string
    middleware=[AnthropicPromptCachingMiddleware()],
)

Paso 7: Hacer que la pizarra sea duradera

Paso 7: Hacer que la pizarra sea duradera funciona mejor cuando se trata como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Prefiera unidades pequeñas y verificables en lugar de scripts extensos. Cuando un paso falla, el fallo debe apuntar a una sola responsabilidad y no a un proceso complicado. Mantenga el estado del gráfico simple y tipado; los bloques anidados ocultan qué nodo escribió qué campo y causan interrupciones en la continuación del proceso. Paso 7: Hacer que la pizarra sea duradera funciona mejor cuando se trata como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Registre los tiempos y el costo de tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando el proceso pasa de la fase de demostración a entornos compartidos.

Lista de verificación operativa

Para la lista de verificación operativa, defina las entradas, el responsable de cada paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto.

Trate esta etapa como un contrato entre las entradas y los resultados validados. Asigne nombres a los artefactos, defina comprobaciones de éxito y rechace las completaciones parciales silenciosas.

Implique la aprobación humana en aquellas tareas que implican gastos o modificaciones en datos de producción. La configuración en tiempo de compilación no equivale a la completitud del proceso empresarial.

Escriba un breve manual de operaciones: cómo rotar claves, cómo vaciar la cola y cómo revertir la última inserción.

Registre los tiempos de ejecución y el costo de tokens o consultas junto con los resultados funcionales. La visibilidad temprana de los costos evita facturas inesperadas al pasar del entorno de demostración a entornos compartidos.

Se debe obtener aprobación humana para las operaciones que implican gastos o modificaciones en los datos de producción. La configuración en tiempo de compilación no equivale a una solución completa para el negocio.

Antes de promocionar la tecnología, congele las versiones, guarde una transcripción de referencia para el camino crítico y confirme los pasos para revertir cambios. Los entornos compartidos requieren límites de velocidad, verificaciones de asignación y un responsable claro para la rotación de credenciales secretas. Prefiera una fiabilidad sencilla a demostraciones ingeniosas pero puntuales.

Nota para el lote 7a480fca3eb9: mantenga las claves del proveedor fuera del repositorio, establezca un límite para los tokens por sesión y almacene las transcripciones junto a los archivos de prueba para que los cambios en los modelos posteriores sigan siendo comparables.

Al trabajar en la nota de fortalecimiento número 0, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código.

Documente tanto el camino óptimo como el de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores.

El detalle de fortalecimiento 0/913: mida el tiempo de ejecución, la clase del error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de anécdotas.

La nota de fortalecimiento 1 funciona mejor cuando se trata como una superficie medible. Capture una transcripción ejemplar, un caso de fallo y la nota de reversión antes de ampliar el alcance. Trate esta etapa como un contrato entre las entradas y los resultados validados. Asigne nombres a los artefactos, defina comprobaciones de éxito y rechace las completaciones parciales silenciosas.

Detalle de refuerzo 1/913: mida el tiempo de ejecución, la clase de error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.

Para la nota de refuerzo 2, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Mantenga la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de secretos y las banderas de funcionalidad deben estar en un lugar que los operadores puedan auditar sin tener que leer todo el grafo.

Detalle de refuerzo 2/913: mida el tiempo de ejecución, la clase de error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.

Al trabajar en la nota de fortalecimiento número 3, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Prefiera unidades pequeñas y verificables a scripts extensos. Cuando un paso falla, el fallo debe apuntar a una única responsabilidad y no a un proceso complicado.

Detalle de fortalecimiento 3/913: mida el tiempo de ejecución, la clase del error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.

La nota de fortalecimiento número 4 funciona mejor cuando se trata como una superficie medible. Capture una transcripción ejemplar, un caso de fallo y la nota de reversión antes de ampliar el alcance. Registre los tiempos y el costo en tokens o consultas junto con los resultados funcionales. La visibilidad temprana de los costos evita facturas inesperadas cuando el proceso pasa de la demostración a entornos compartidos.

Detalle de fortalecimiento 4/913: mida el tiempo de ejecución, la clase de error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.

Para la nota de fortalecimiento 5, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Documente tanto la ruta óptima como la ruta de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores.

Detalle de fortalecimiento 5/913: mida el tiempo de ejecución, la clase de error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.

Al trabajar en la nota de fortalecimiento número 6, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Trate esta etapa como un contrato entre las entradas y los resultados validados. Asigne nombres a los artefactos, defina las comprobaciones de éxito y rechace las completaciones parciales silenciosas.

Detalle de fortalecimiento 6/913: mida el tiempo de ejecución, la clase del error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.

La nota de fortalecimiento número 7 funciona mejor cuando se trata como una superficie medible. Capture una transcripción de referencia, un caso de fallo y la nota de reversión antes de ampliar el alcance. Mantenga la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de secretos y las banderas de funcionalidad deben estar en un lugar que los operadores puedan auditar sin tener que leer todo el sistema.

Detalle de refuerzo 7/913: mida el tiempo de ejecución, la clase de error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.

Para la nota de refuerzo 8, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Prefiera unidades pequeñas y verificables sobre scripts extensos. Cuando un paso falla, el fallo debe apuntar a una única responsabilidad en lugar de a un proceso complicado.

Detalle de refuerzo 8/913: mida el tiempo de ejecución, la clase de error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.

Al trabajar en la nota de fortalecimiento número 9, anote primero el contrato: los datos requeridos, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Registre los tiempos y el costo de tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando el proceso pasa de la fase de demostración a entornos compartidos.

Detalle de fortalecimiento 9/913: mida el tiempo real empleado, la clase del error y el gasto en tokens para esta nota, y luego decida si mantener la modificación basándose en un conjunto fijo de preguntas en lugar de en observaciones anecdóticas.

La nota de fortalecimiento número 10 funciona mejor cuando se trata como una superficie medible. Capture una transcripción ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Documente tanto el camino óptimo como el camino de recuperación. Los intentos repetidos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son algo que se añade posteriormente.

Detalle de reforzamiento 10/913: mida el tiempo de ejecución, la clase de error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.

Para la nota de reforzamiento 11, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Trate esta etapa como un contrato entre las entradas y los resultados validados. Asigne nombres a los artefactos, defina verificaciones de éxito y rechace las completaciones parciales silenciosas.

Detalle de reforzamiento 11/913: mida el tiempo de ejecución, la clase de error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.

Al trabajar en la nota de fortalecimiento 12, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código.

Mantenga la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de secretos y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin tener que leer todo el sistema.

Detalle de fortalecimiento 12/913: mida el tiempo de ejecución, la clase del error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.

La nota de fortalecimiento 13 funciona mejor cuando se trata como una superficie medible. Capture una transcripción de referencia, un caso de fallo y la nota de reversión antes de ampliar el alcance.

Preferir unidades pequeñas y verificables sobre scripts extensos. Cuando un paso falla, el fallo debe apuntar a una sola responsabilidad en lugar de a un proceso complicado.

Detalle de refuerzo 13/913: mida el tiempo de ejecución, la clase de error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.

Para la nota de refuerzo 14, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Registre los tiempos y el costo en tokens o consultas junto con los resultados funcionales. La visibilidad temprana de los costos evita facturas inesperadas cuando el proceso pasa de entornos de demostración a entornos compartidos.

Detalle de refuerzo 14/913: mida el tiempo de ejecución, la clase de error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.

Al trabajar en la nota de fortalecimiento 15, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código.

Documente tanto el camino óptimo como el de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras realizadas posteriormente.

Detalle de fortalecimiento 15/913: mida el tiempo de ejecución, la clase del error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.