Módulo 6: Functional API

Introducción: Otra Forma de Construir Agentes

Descripción

En el Módulo 5 construiste workflows con StateGraph. Definiste nodos como funciones, los conectaste con edges y conditional edges, diseñaste estado tipado con TypedDict y Annotated, y visualizaste tus grafos con draw_mermaid_png(). Potente, explícito, visual. Todo funciona.

Pero miraste el código y pensaste: "para un pipeline que es básicamente get query → descomponer → buscar → sintetizar... ¿necesito definir un StateGraph con nodos, edges, compilar, y todo lo demás? Eso son funciones llamando funciones."

Sí. Algunos workflows no necesitan grafos explícitos. Un pipeline de investigación es esencialmente una función que llama a otras funciones en secuencia, con algo de branching y error handling. Forzarlo en un grafo explícito agrega ceremonia sin agregar claridad.

La Functional API de LangGraph te deja escribir ese pipeline como Python normal — y obtener los superpoderes de LangGraph (durabilidad, checkpointing, streaming) automáticamente. No es la versión "fácil" de la Graph API. Es una forma diferente de expresar workflows, optimizada para flujos que se leen como código Python secuencial.


¿Dónde estamos en la guía?

Este es el Módulo 6 de la guía LangChain & LangGraph: From Chains to Agents. Es el segundo módulo del Bloque 2 (LangGraph Fundamentals).

Bloque 1: LangChain Core (Módulos 1-4)           ✅ Completado
Bloque 2: LangGraph Fundamentals (Módulos 5-7)   ← ESTÁS AQUÍ (Módulo 6)
Bloque 3: LangGraph Avanzado (Módulos 8-10)
Bloque 4: Producción (Módulos 11-12)
Tu progreso:

Bloque 1 — LangChain Core                   ✅ Completado
    │
    │  Módulo 1: Modelos y Proveedores       ✅
    │  Módulo 2: Tools y Tool Calling        ✅
    │  Módulo 3: Agents (create_agent)       ✅
    │  Módulo 4: Middleware y Customización   ✅
    │
    ▼
Bloque 2 — LangGraph Fundamentals
    │
    │  Módulo 5: Introducción a LangGraph    ✅ Completado
    │  Módulo 6: Functional API              ← ESTÁS AQUÍ
    │  Módulo 7: Flujos Avanzados            🔒 Siguiente
    │
    ▼
Bloques 3-4 — Avanzado + Producción         🔒

En el Módulo 5 dominaste la Graph API: StateGraph, nodos, edges, conditional edges, estado tipado, compilación, visualización. Ahora aprendes la alternativa: la Functional API, que te permite expresar workflows como funciones Python con decoradores.


El puente: de grafos explícitos a funciones con superpoderes

Lo que ya sabes hacer

En el Módulo 5 construiste workflows como este:

from typing import TypedDict, Annotated
import operator
from langgraph.graph import StateGraph, START, END

class ResearchState(TypedDict):
    messages: Annotated[list[str], operator.add]
    query: str
    results: Annotated[list[str], operator.add]

def decompose(state: ResearchState) -> dict:
    return {"messages": ["Descomponiendo query..."], "results": [f"Sub-query de: {state['query']}"]}

def search(state: ResearchState) -> dict:
    return {"messages": ["Buscando información..."], "results": ["Resultado de búsqueda"]}

def synthesize(state: ResearchState) -> dict:
    return {"messages": [f"Síntesis: {len(state['results'])} resultados procesados"]}

graph_builder = StateGraph(ResearchState)
graph_builder.add_node("decompose", decompose)
graph_builder.add_node("search", search)
graph_builder.add_node("synthesize", synthesize)
graph_builder.add_edge(START, "decompose")
graph_builder.add_edge("decompose", "search")
graph_builder.add_edge("search", "synthesize")
graph_builder.add_edge("synthesize", END)

graph = graph_builder.compile()
result = graph.invoke({"messages": [], "query": "¿Qué es prompt engineering?", "results": []})
print(result["messages"])
# ['Descomponiendo query...', 'Buscando información...', 'Síntesis: 2 resultados procesados']

Funciona. Pero mira la estructura: es una secuencia lineal. START → decompose → search → synthesize → END. No hay branching complejo, no hay conditional edges. Es, en esencia, tres funciones llamándose en secuencia.

Lo que aprenderás aquí

El mismo pipeline, con la Functional API:

from langgraph.func import entrypoint, task

@task
def decompose(query: str) -> list[str]:
    return [f"Sub-query de: {query}"]

@task
def search(sub_queries: list[str]) -> list[str]:
    return ["Resultado de búsqueda"]

@task
def synthesize(results: list[str]) -> str:
    return f"Síntesis: {len(results)} resultados procesados"

@entrypoint()
def research_agent(query: str) -> str:
    sub_queries = decompose(query).result()
    results = search(sub_queries).result()
    summary = synthesize(results).result()
    return summary

result = research_agent.invoke("¿Qué es prompt engineering?")
print(result)
# Síntesis: 1 resultados procesados

Lee el código de research_agent. Es Python normal: llama funciones, guarda resultados en variables, retorna un valor. Pero por debajo, LangGraph está construyendo un grafo implícito, gestionando checkpoints de cada @task, y habilitando streaming de progreso.

Parece Python. Tiene superpoderes.


La motivación: no todo necesita un grafo explícito

La Graph API de LangGraph brilla cuando tu workflow tiene topología compleja:

         ┌──── code_handler ────┐
         │                      │
START → classify ─── qa_handler ──── END
         │                      │
         └── creative_handler ──┘

Ese diagrama tiene branching condicional. La Graph API lo expresa perfectamente: defines nodos, les pones conditional edges, compilas, y visualizas con draw_mermaid_png().

Pero muchos workflows del mundo real son secuenciales:

query → descomponer → buscar → analizar → sintetizar → output

Forzar esa secuencia en un grafo explícito con StateGraph, add_node, add_edge, TypedDict con reducers, y compilación... agrega ceremonia sin agregar claridad. Es como usar un diagrama de flujo para describir una receta de cocina: técnicamente correcto, pero una lista de pasos sería más clara.

La Functional API existe para esos casos. Escribes la secuencia como funciones Python, y LangGraph agrega la infraestructura por debajo.


Qué es la Functional API

La Functional API de LangGraph usa dos decoradores:

DecoradorQué haceEquivalente en Graph API
@entrypointDefine el punto de entrada del workflow. Es tu función principal.StateGraph + compile()
@taskDefine una unidad de trabajo independiente. Retorna un Future.Un nodo (add_node)
from langgraph.func import entrypoint, task

Lo que obtienes gratis al usar estos decoradores:

  • Durabilidad: si el workflow crashea, el checkpointing permite retomarlo desde el último @task completado
  • Streaming: puedes streamear el progreso del workflow paso a paso
  • Human-in-the-loop: puedes pausar el workflow con interrupt() para pedir aprobación humana
  • Misma interfaz: workflow.invoke() y workflow.stream() — idéntico a un grafo compilado

Lo que parece Python normal, tiene la infraestructura de LangGraph por debajo. Esa es la idea central.


Dos APIs, un toolkit

Graph API y Functional API no compiten. Son dos formas de expresar workflows que comparten el mismo runtime:

AspectoGraph API (StateGraph)Functional API (@entrypoint)
Cómo defines el flujoNodos + edges explícitosControl flow de Python (if, for, try)
EstadoTypedDict con reducersVariables locales de la función
Visualizacióndraw_mermaid_png()No disponible (grafo se genera en runtime)
CheckpointingCheckpoint después de cada superstepCheckpoint por cada @task completado
Ideal paraTopologías complejas, branching visualFlujos secuenciales, branching con Python
Curva de aprendizajeMayor (nuevo paradigma de grafos)Menor (es Python con decoradores)
VerbosidadMás código de setupMenos código de setup

Puedes mezclar ambas APIs en el mismo proyecto. Un @entrypoint puede llamar a un StateGraph compilado, y un nodo de StateGraph puede usar @task. No es una decisión permanente — es una decisión por workflow.

La regla de decisión

¿Tu workflow tiene más de 5 nodos con routing condicional complejo?
    → Graph API (StateGraph). La visualización te va a salvar.

¿Es un flujo secuencial con branching simple (if/else, try/except)?
    → Functional API (@entrypoint + @task). Lee como Python, tiene superpoderes.

¿No estás seguro?
    → Empieza con Functional API. Es más rápido de prototipar.
       Si el flujo se complica, migra a Graph API.

Mapa del módulo

CápsulaTemaQué aprenderás
02@entrypoint: definir un agente como funciónDecorador @entrypoint(), parámetros inyectables, ejecución con invoke y stream, comparación side-by-side con StateGraph
03@task: tareas que componen el agenteDecorador @task, Futures y .result(), tareas como unidades checkpointeables, cuándo usar @task vs código directo
04Control flow nativowhile loops para agent loops, if/else para routing, try/except para error handling, for loops para iteración — todo sin edges explícitos
05Graph API vs Functional API: comparación profundaTabla comparativa detallada, el mismo problema resuelto con ambas APIs, criterios de migración, ventajas de cada approach
06Patterns con Functional APITool execution pattern, multi-step reasoning, parallel task execution con futures, composición de tasks
07Combinar Graph y Functional APIUsar @task dentro de StateGraph, llamar grafos compilados desde @entrypoint, cuándo la combinación tiene sentido
08Proyecto evolutivo: Research Agent baseAI Research Assistant v1 con Functional API — recibe tema, descompone, busca, sintetiza reporte structured

Flujo de aprendizaje: Empiezas entendiendo @entrypoint como el equivalente funcional de StateGraph (02). Luego dominas @task y el concepto de Futures (03). Con ambos decoradores, aprendes a dirigir el flujo con Python nativo (04). Después desarrollas criterio comparando ambas APIs en profundidad (05). Con ese criterio, aprendes patterns profesionales (06) y cómo combinar ambas APIs (07). Finalmente, construyes la primera versión del proyecto evolutivo (08).


El proyecto evolutivo empieza aquí

Este módulo marca un cambio importante en la guía. En los Módulos 1-5, cada módulo tenía su propio mini-proyecto independiente. A partir de ahora, construyes un solo proyecto que evoluciona módulo a módulo: el AI Research Assistant.

Módulo 6:  Research Agent base (Functional API)
    │
    ▼
Módulo 7:  + Retry logic, branching paralelo, error handling
    │
    ▼
Módulo 8:  + Persistencia (checkpointing, memoria)
    │
    ▼
Módulo 9:  + Aprobaciones humanas (human-in-the-loop)
    │
    ▼
Módulo 10: + Multi-agente (researcher, analyst, writer, supervisor)
    │
    ▼
Módulo 11: + Deep Agent (planning, filesystem, subagents)
    │
    ▼
Módulo 12: + Observability y producción (LangSmith, evaluation)

Lo que construyas en este módulo será la base de 6 módulos más de iteración. La v1 es simple pero funcional: recibe un tema de investigación, descompone la tarea en sub-queries con un LLM, ejecuta búsquedas, y genera un resumen structured. Cada módulo posterior agrega una capa de sofisticación.

Haz la v1 bien. Vas a iterar sobre ella durante mucho tiempo.

Qué hace el Research Assistant v1

En la Cápsula 08 de este módulo construirás un workflow funcional que:

  1. Recibe un tema de investigación — una pregunta o tema que el usuario quiere entender
  2. Descompone la tarea con un LLM — genera sub-queries específicas para investigar diferentes ángulos del tema
  3. Ejecuta búsquedas con @task — cada sub-query busca información (con tools o búsqueda simulada)
  4. Sintetiza un reporte — combina los resultados en una respuesta structured con secciones, fuentes, y conclusiones

Es simple comparado con lo que será en el Módulo 12. Pero es funcional end-to-end, y cada pieza que construyas aquí (@entrypoint, @task, el flujo de descomposición → búsqueda → síntesis) sobrevive hasta la versión final.


Qué NO cubre este módulo

  • Flujos avanzados (ciclos con retry, branching paralelo, subgraphs) — Se cubre en Módulo 7. Aquí dominas los fundamentos de la Functional API.
  • Persistencia (checkpointing, memoria entre sesiones) — Se cubre en Módulo 8. Aquí verás un preview del concepto, pero no profundizamos.
  • Human-in-the-loop (interrupts, approvals) — Se cubre en Módulo 9. Mencionaremos que la Functional API lo habilita con interrupt(), pero no lo implementamos.
  • Multi-agent systems — Se cubre en Módulo 10. Aquí trabajas con un solo workflow funcional.
  • Deep Agents — Se cubre en Módulo 11. Aquí construyes con LangGraph directo.

Lo que pasa por debajo: no es solo Python

La Functional API parece "solo escribir Python." Y esa es la intención: que parezca familiar. Pero por debajo, LangGraph está haciendo trabajo serio:

  1. Grafo implícito: Cuando LangGraph ejecuta tu @entrypoint, construye un grafo de ejecución en runtime basado en los @task que llamas. No lo ves, pero existe.
  2. Checkpointing automático: Cada @task completado se guarda en un checkpoint. Si tu workflow falla después de 3 de 5 tasks, al retomar, las 3 primeras no se re-ejecutan.
  3. Streaming granular: Cada @task emite un evento en el stream. Puedes dar feedback progresivo al usuario sin implementar nada extra.
  4. Soporte para interrupts: Puedes pausar tu workflow con interrupt() en cualquier punto para pedir input humano. LangGraph maneja la pausa y la reanudación.

Esa es la diferencia entre "escribir Python" y "escribir Python con @entrypoint". Parece igual. No lo es.


Setup técnico

Prerequisitos

Antes de continuar, verifica que tienes:

  • Módulo 5 completado — sabes crear grafos con StateGraph, nodos, edges, conditional edges, estado tipado, compilación y ejecución
  • Python 3.11+ instalado
  • ✅ Al menos una API key de un proveedor (OpenAI recomendado para este módulo)

Instalación

Si completaste el Módulo 5, ya tienes todo instalado. Verifica:

pip install langgraph langchain-openai python-dotenv

La Functional API viene incluida en langgraph — no hay paquetes adicionales:

from langgraph.func import entrypoint, task
print("Functional API disponible")
# Output esperado: Functional API disponible

Verificar que todo funciona

from langgraph.func import entrypoint, task

@task
def greet(name: str) -> str:
    return f"¡Hola, {name}!"

@entrypoint()
def my_workflow(name: str) -> str:
    greeting = greet(name).result()
    return greeting

result = my_workflow.invoke("LangGraph")
print(result)
# Output esperado: ¡Hola, LangGraph!

Si ves el saludo, tu setup está listo para la Functional API.

Si algo falla:

ErrorCausaSolución
ImportError: cannot import name 'entrypoint' from 'langgraph.func'Versión de langgraph antiguapip install --upgrade langgraph (necesitas v0.2.60+)
TypeError: 'task' object is not callableLlamaste @task sin estar dentro de un @entrypointLos @task solo pueden ejecutarse dentro de un @entrypoint o de un nodo de StateGraph
SerializationError al usar invokeInput o output no es JSON-serializableUsa tipos primitivos (dict, list, str, int, bool). No pases objetos custom como input

Evidencia de éxito

Al terminar este módulo, sabrás que tuviste éxito si:

  • ✅ Puedes crear workflows con @entrypoint como punto de entrada y @task para tareas independientes
  • ✅ Entiendes que @task retorna un Future y sabes usar .result() para obtener el valor
  • ✅ Usas control flow nativo de Python (if/else, for, try/except) para dirigir la ejecución sin edges explícitos
  • ✅ Puedes comparar Graph API vs Functional API y decidir cuándo usar cada una
  • ✅ Sabes combinar ambas APIs cuando el caso lo requiere
  • ✅ Tu AI Research Assistant v1 funciona end-to-end: tema → descomposición → búsqueda → síntesis

Vista previa: del workflow funcional a flujos avanzados

En este módulo construirás workflows con la Functional API: @entrypoint para definir el punto de entrada, @task para las unidades de trabajo, y Python nativo para el control flow. El resultado será un Research Agent que funciona, pero con flujo lineal y sin manejo de errores robusto.

En el Módulo 7 (Flujos Avanzados), le agregarás patrones de producción: retry con backoff cuando una API falla, branching paralelo para buscar en múltiples fuentes simultáneamente, subgraphs para encapsular lógica, y error handling que hace tu workflow resiliente.

El Research Agent pasará de "funciona en el happy path" a "funciona en el mundo real."


Resumen

  • En el Módulo 5 dominaste la Graph API: StateGraph, nodos, edges, conditional edges, estado tipado, compilación, y visualización
  • La Functional API es una forma alternativa de construir workflows en LangGraph — usa decoradores (@entrypoint, @task) y control flow de Python en vez de grafos explícitos
  • No es la versión fácil. Es una forma diferente, optimizada para flujos que se leen como código Python secuencial
  • Parece Python normal, pero tiene superpoderes: durabilidad, checkpointing, streaming, human-in-the-loop — todo viene gratis con los decoradores
  • Graph API y Functional API comparten el mismo runtime. Son complementarias, no competidoras. Puedes mezclarlas en el mismo proyecto
  • Regla de decisión: >5 nodos con routing complejo → Graph API. Flujo secuencial con branching simple → Functional API. No estás seguro → empieza con Functional
  • El proyecto evolutivo empieza aquí. El AI Research Assistant v1 será la base de 6 módulos más de iteración
  • La Functional API no soporta visualización con draw_mermaid_png() — el grafo se genera dinámicamente en runtime

Recursos adicionales

  1. Functional API Overview — Documentación oficial de la Functional API de LangGraph
  2. How to use the Functional API — Guía práctica con ejemplos paso a paso
  3. Choosing between Graph API and Functional API — Criterios oficiales para elegir entre ambas APIs
  4. Introducing the LangGraph Functional API — Blog post de lanzamiento con motivación y ejemplos
  5. @entrypoint Reference — Referencia completa del decorador @entrypoint
  6. @task Reference — Referencia completa del decorador @task

Módulo 6 — LangChain & LangGraph: From Chains to Agents

Siguiente cápsula: @entrypoint: Definir un Agente como Función — aprenderás cómo @entrypoint reemplaza a StateGraph + compile() y cómo ejecutar workflows funcionales con invoke y stream.