Inicio / Artículos / Notas prácticas: Dale a tu agente de IA una memoria; luego observa todo lo que hace.

Notas prácticas: Dale a tu agente de IA una memoria; luego observa todo lo que hace.

Guía paso a paso práctica: Dale a tu agente de IA una memoria, y luego observa todo lo que hace: contratos, verificaciones y espacios para código integrable para los equipos que implementan este patrón.

3610 palabras

Esta guía reconstruye el proceso desde las materias primas hasta un sistema funcional para: Darle a tu agente de IA una memoria, y luego observar cómo lo hace el autor con LangSmith. El enfoque está en pasos operativos, verificaciones explícitas y código que puedes insertar directamente en un repositorio sin tener que adivinar su propósito. En la etapa de visión general, define 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. Mantén la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de datos confidenciales y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin necesidad de leer todo el sistema.

La arquitectura

Al trabajar en la etapa de Arquitectura, 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 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.

                    ┌─────────────────────┐
                    │       User          │
                    └──────────┬──────────┘
                               │
                               ▼
                    ┌─────────────────────┐
                    │    AI Agent         │
                    │  LangChain Agent    │
                    └──────────┬──────────┘
                               │
                 ┌─────────────┴─────────────┐
                 │                           │
                 ▼                           ▼
        ┌─────────────────┐        ┌──────────────────┐
        │ Conversation    │        │     Tools        │
        │ Memory          │        │                  │
        │ InMemorySaver   │        │ Tavily Web Search│
        └─────────────────┘        └──────────────────┘
                 │                           │
                 └─────────────┬─────────────┘
                               │
                               ▼
                    ┌─────────────────────┐
                    │     Ollama          │
                    │     Llama 3.2       │
                    └─────────────────────┘
                               │
                               ▼
                    ┌─────────────────────┐
                    │     LangSmith       │
                    │  Traces & Debugging │
                    └─────────────────────┘

1. Ejecutar un LLM localmente con Ollama

Al trabajar en la etapa 1 de Ejecución de un LLM, 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 probables sobre scripts extensos. Cuando un paso falla, el fallo debe apuntar a una única responsabilidad y no a un proceso complicado. Registre el ID de la solicitud, el ID del modelo y la latencia en cada llamada. Sin ese registro, los errores intermitentes del proveedor parecen bugs de la aplicación.

from langchain_ollama import ChatOllama
llm = ChatOllama(
    model="llama3.2:latest",
    base_url="http://localhost:11434",
    temperature=0,
)

model

Al trabajar en la fase del modelo, 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 fase como un contrato entre las entradas y las salidas validadas. Asigne nombres a los artefactos, defina comprobaciones de éxito y rechace las completaciones parciales silenciosas. Almacene en caché las instrucciones del sistema estables y los esquemas de las herramientas. Reenviar un preámbulo idéntico es una causa común de desperdicio.

model="llama3.2:latest"

Al trabajar en la fase del modelo, 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.

base_url

La etapa baseurl funciona mejor cuando se trata como una superficie medible. Capture un registro exitoso, 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 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 del proceso.

base_url="http://localhost:11434"

temperature

La etapa de temperatura funciona mejor cuando se trata como una superficie medible. Capture un registro exitoso, 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 de los gráficos simple y tipado. Los bloques anidados ocultan qué nodo escribió qué campo y provocan interrupciones en la continuación del proceso.

temperature=0

2. Creación del agente

La etapa 2, “Crear el agente”, 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. Trate esta etapa como un contrato entre las entradas y las salidas validadas. Asigne nombres a los artefactos, defina verificaciones de éxito y rechace las completaciones parciales silenciosas. 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. La etapa 2, “Crear el agente”, 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. 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.

from langchain.agents import create_agent
agent = create_agent(
    model=llm
)
agent = create_agent(
    model=llm,
    tools=[tool1],
    system_prompt="You are an intelligent knowlegable agent"
)

3. Darle al agente una herramienta de búsqueda en la web

En la fase de 3 “Giving the Agent”, 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. Autentique en la pasarela y vuelva a autorizar en el plano de datos. Un token portador por sí solo no constituye un límite entre tenencias.

from langchain.tools import tool
@tool("web_search", description="Search the web for information")
def tool1(query: str) -> Dict[str, Any]:
    tavily = TavilyClient()
    return tavily.search(query=query)
tavily = TavilyClient()
return tavily.search(query=query)
User Question
      │
      ▼
     LLM
      │
      │ "I need external information"
      ▼
  Web Search Tool
      │
      ▼
   Tavily API
      │
      ▼
 Search Results
      │
      ▼
     LLM
      │
      ▼
 Final Answer

4. El problema: Los LLM no recuerdan automáticamente al autor

En la fase 4 de The Problem LLMs, 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. Prefiera unidades pequeñas y verificables sobre scripts extensos. Cuando un paso falla, el error debe indicar una única responsabilidad y no un proceso complicado. Prefiera salidas estructuradas con validación de esquema sobre texto libre cuando el paso siguiente sea código o una llamada a una herramienta.

from langgraph.checkpoint.memory import InMemorySaver
agent = create_agent(
    model=llm,
    checkpointer=InMemorySaver()
)
Question → LLM → Answer

5. InMemorySaver — Darle memoria al Agente

Para la etapa de 5 InMemorySaver Giving, 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. Incluya la aprobación humana en aquellos casos en que se gasten fondos o se modifiquen datos de producción. La conexión en tiempo de compilación no equivale a la completitud del proceso empresarial. Para la etapa de 5 InMemorySaver Giving, 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 contenido.

gráfico.

checkpointer=InMemorySaver()

6. La línea más importante: thread_id

Al trabajar en la etapa 6 de las más importantes, 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 de 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.

config = {
    "configurable": {
        "thread_id": "1"
    }
}
Thread 1
────────────
User → My favorite color is Green
AI   → Great!
User → What's my favorite color?
AI   → Green
Thread 2
────────────
User → My favorite color is Blue
AI   → Blue

7. Primera conversación

Al trabajar en la etapa 7 de Conversación Inicial, anote primero el contrato: los datos necesarios, 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 del código. Prefiera unidades pequeñas y verificables en lugar de scripts extensos. Cuando un paso falla, el fallo debe apuntar a una única responsabilidad y no a un proceso complicado. Haga una verificación después de los pasos costosos. El sistema de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador intenta nuevamente un nodo posterior.

question = HumanMessage(
    content="I am X my favorite color is Green"
)
response = agent.invoke(
    {"messages": [question]},
    config,
)
"thread_id": "1"

8. Preguntarle al Agente más tarde

Al trabajar en la etapa 8 de “Preguntar al agente”, anote primero el contrato: los datos de entrada 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. Considere esta etapa como un contrato entre los datos de entrada y los resultados validados. Asigne nombres a los artefactos, defina las comprobaciones de éxito y evite completaciones parciales silenciosas. Haga una verificación 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. Al trabajar en la etapa 8 de “Preguntar al agente”, anote primero el contrato: los datos de entrada 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. 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.

question2 = HumanMessage(
    content="What's my favorite color?"
)
response2 = agent.invoke(
    {"messages": [question2]},
    config,
)
config = {
    "configurable": {
        "thread_id": "1"
    }
}
Your favorite color is Green!

9. Por qué thread_id es tan importante

La etapa de “9 razones por las que importa thread_id” funciona mejor cuando se trata como un elemento medible. Capture una transcripción clave, 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 grafo simple y tipado. Los bloques anidados ocultan qué nodo escribió qué campo y dificultan la reanudación después de interrupciones.

Customer A → thread_id = "customer-A"
Customer B → thread_id = "customer-B"
Customer C → thread_id = "customer-C"
AI Agent
                │
       ┌────────┼────────┐
       ▼        ▼        ▼
   Customer A Customer B Customer C
      │           │          │
   Thread A    Thread B   Thread C

10. Pero la memoria no es suficiente

La etapa 10 “But Memory Isn” funciona mejor cuando se trata como una superficie medible. Capture una transcripción clave, 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 única 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.

User Question
     ↓
Agent
     ↓
LLM decides to call web_search
     ↓
Tavily
     ↓
Search results
     ↓
LLM
     ↓
Final answer

11. Ingrese a LangSmith

La etapa 11 de Enter LangSmith funciona mejor cuando se trata como una superficie medible. Capture un transcripte ideal, 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 las salidas validadas. Asigne nombres a los artefactos, defina comprobaciones de éxito y rechace completaciones parciales silenciosas. 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. La etapa 11 de Enter LangSmith funciona mejor cuando se trata como una superficie medible. Capture un transcripte ideal, 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.

os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_API_KEY"] = "YYY"
os.environ["LANGSMITH_ENDPOINT"] = "https://langsmith-endpoint"
os.environ["LANGSMITH_PROJECT"] = "local-ollama-agent"
LANGSMITH_TRACING=true

12. Por qué el rastreo es mejor que print()

En la fase de rastreo de los 12 porqués, 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. 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. Incluya la aprobación humana en aquellos casos que impliquen gastos o cambios en los datos de producción. La configuración en tiempo de compilación no equivale a la completitud del proceso empresarial.

print(response)
Question
   │
   ├── LLM call
   │
   ├── Tool decision
   │
   ├── Web search
   │
   ├── Tool response
   │
   ├── Another LLM call
   │
   └── Final response

13. ¿Qué podemos aprender de un rastreo?

Para la etapa 13 “¿Qué podemos hacer?”, se deben definir los insumos, 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. Es preferible utilizar unidades pequeñas y verificables en lugar de scripts extensos. Cuando un paso falla, el error debe indicar una única responsabilidad y no un proceso complicado. Se debe incluir la aprobación humana en aquellos casos en que se gastan fondos o se modifican datos de producción. La configuración en tiempo de compilación no equivale a la completitud del proceso empresarial.

Total execution: 8 seconds
LLM call              1.5 sec
Web search             5.2 sec
Final LLM call         1.3 sec

14. Combinar memoria y capacidad de observación

En la etapa 14 de Implementación de Memoria, se deben definir 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. Considere 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. Incluya la aprobación humana en aquellos casos en que se gasten fondos o se modifiquen datos de producción. La conexión en tiempo de compilación no equivale a la completitud del proceso empresarial. En la etapa 14 de Implementación de Memoria, se deben definir 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 datos secretos y las banderas de funcionalidad deben estar en un lugar que los operadores puedan auditar sin necesidad de leer todo el sistema.

                         ┌───────────────┐
                         │     User      │
                         └───────┬───────┘
                                 │
                                 ▼
                      ┌────────────────────┐
                      │     AI Agent       │
                      └─────────┬──────────┘
                                │
                 ┌──────────────┼──────────────┐
                 │              │              │
                 ▼              ▼              ▼
             Memory          LLM            Tools
          InMemorySaver     Ollama          Tavily
                 │              │              │
                 └──────────────┼──────────────┘
                                │
                                ▼
                         ┌─────────────┐
                         │ LangSmith   │
                         │   Tracing   │
                         └─────────────┘

Memoria

Al trabajar en la etapa de Memoria, 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 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. La función de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador vuelve a intentar un nodo posterior.

LLM

Al trabajar en la fase del LLM, 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 probables sobre scripts extensos. Cuando un paso falla, el fallo debe apuntar a una única responsabilidad y no a un proceso complicado. Almacene en caché las instrucciones del sistema estables y los esquemas de las herramientas. Reenviar un preámbulo idéntico es una causa común de desperdicio.

Herramientas

Al trabajar en la etapa de Herramientas, anote primero el contrato: los datos de entrada 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. Considere esta etapa como un contrato entre los datos de entrada y los resultados validados. Asigne nombres a los artefactos, defina las comprobaciones de éxito y evite completaciones parciales silenciosas. Registre el nombre de la herramienta, el hash de los argumentos, la latencia y el resultado de cada llamada. Depurar sin ese historial desperdicia horas. Al trabajar en la etapa de Herramientas, anote primero el contrato: los datos de entrada 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. 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 tener que leer todo el sistema.

LangSmith

La etapa de LangSmith funciona mejor cuando se trata como una superficie medible. Capture un transcripte exitoso, 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 juntos. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores. Mantenga el estado de los gráficos simple y tipado. Los bloques anidados ocultan qué nodo escribió qué campo y provocan interrupciones en la continuación después de las interrupciones.

15. El flujo conceptual completo

La etapa 15, “Conceptual completo”, funciona mejor cuando se trata como una superficie medible. Capture un registro exitoso, 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 grafo simple y tipado; los bloques anidados ocultan qué nodo escribió qué campo y causan interrupciones en la continuación del proceso.

Paso 1: El usuario proporciona información

El enfoque más efectivo cuando el usuario de la Etapa 1 proporciona los datos es tratarlos como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Considere esta etapa como un contrato entre las entradas y los resultados validados. Asigne nombres a los artefactos, defina verificaciones de éxito y rechace completaciones parciales silenciosas. 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.

"My name is Amit and my favorite color is Green."

El enfoque más efectivo cuando el usuario de la Etapa 1 proporciona los datos es tratarlos como una superficie medible. Capture un registro ideal, 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 único lugar que los operadores puedan auditar sin tener que leer todo el grafo.

thread_id = 1

Etapa 2: El usuario hace otra pregunta

En la etapa 2, cuando el usuario hace una consulta, se deben definir los datos de entrada, 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. Se debe documentar tanto la ruta óptima como la ruta de recuperación. Las intentonas repetidas, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores. Se debe incluir la aprobación humana en aquellos casos en que se gastan fondos o se modifican datos de producción. La configuración en tiempo de compilación no equivale a la completitud del proceso empresarial.

"What's my favorite color?"
"Your favorite color is Green."

Etapa 3: El usuario hace una pregunta de conocimiento

En la etapa 3, el usuario debe definir 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. Es preferible utilizar 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. Se debe incluir 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 una solución completa desde el punto de vista empresarial.

"Who is the Chief Minister of Tamil Nadu?"
web_search

Etapa 4: Ejecución de la herramienta

En la etapa en la que ejecuta la herramienta de Paso 4, 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 comprobaciones de éxito y rechace las completaciones parciales silenciosas. Autentíquese en la pasarela y vuelva a autorizarse en el plano de datos. Un token portador por sí solo no constituye un límite entre tenencias. En la etapa en la que ejecuta la herramienta de Paso 4, 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 sistema.

Paso 5 — El LLM genera la respuesta

Al trabajar en la etapa de generación del LLM del Paso 5, 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.

Paso 6 — LangSmith registra la ejecución

16. Una nota sobre los secretos

os.environ["TAVILY_API_KEY"] = "XXX"
os.environ["LANGSMITH_API_KEY"] = "YYY"
export TAVILY_API_KEY="..."
export LANGSMITH_API_KEY="..."
export LANGSMITH_TRACING="true"
export LANGSMITH_PROJECT="local-ollama-agent"

17. Por qué es importante esta arquitectura

User → LLM → Response
┌── Memory
                   │
User → Agent → LLM ├── Tools
                   │
                   └── State
                        │
                        ▼
                    Tracing

18. Memoria versus persistencia

InMemorySaver()
Application starts
      ↓
Thread 1 created
      ↓
Conversation stored in memory
      ↓
Application restarts
      ↓
Memory is gone

19. Un modelo mental simple

1⃣ Agente

agent = create_agent(...)

2⃣ Modelo

llm = ChatOllama(...)

3⃣ Memoria

checkpointer=InMemorySaver()

4⃣ Observabilidad

LANGSMITH_TRACING=true
Agent
 ├── Model
 ├── Memory
 ├── Tools
 └── Observability

Conclusión

Ollama
   +
Llama 3.2
   +
LangChain Agent
   +
InMemorySaver
   +
Tavily
   +
LangSmith

¿Qué viene después?

Código fuente

Lista de verificación operativa