skills/langgraph-functional-api/SKILL.md
LangGraph Functional API (Python) — build stateful agent workflows with @entrypoint and @task decorators. Imperative Python style with LangGraph persistence, streaming, HITL, and durable execution. Ideal for wrapping existing agents (CrewAI, AutoGen, Strands) or complex parallel task logic.
npx skillsauth add enuno/claude-command-and-control langgraph-functional-apiInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Expert assistance for the LangGraph Functional API: imperative, Python-native agent workflows using @entrypoint and @task decorators. Gets you LangGraph persistence, streaming, and human-in-the-loop with minimal boilerplate — especially useful for wrapping existing agents or frameworks.
When to choose Functional API over Graph API:
Full corpus: ../langgraph/references/llms-txt.md (5.4 MB) and ../../langchain-deepagents/references/llms-full.md (10 MB).
Activate when:
exit, async, or sync durability modesfrom langgraph.checkpoint.memory import InMemorySaver
from langgraph.func import entrypoint, task
@task
def fetch_data(query: str) -> str:
return call_api(query) # Any IO operation
@task
def process_data(raw: str) -> str:
return transform(raw)
@entrypoint(checkpointer=InMemorySaver())
def my_workflow(inputs: dict) -> dict:
raw = fetch_data(inputs["query"]).result()
processed = process_data(raw).result()
return {"output": processed}
# Invoke with thread_id for persistence
result = my_workflow.invoke(
{"query": "hello"},
config={"configurable": {"thread_id": "1"}},
)
from langgraph.func import entrypoint, task
@task
def search_web(query: str) -> str:
return web_search(query)
@task
def search_docs(query: str) -> str:
return doc_search(query)
@entrypoint(checkpointer=InMemorySaver())
def research_workflow(inputs: dict) -> dict:
# Launch both tasks concurrently
web_future = search_web(inputs["query"])
docs_future = search_docs(inputs["query"])
# Collect results (blocks until both done)
web_result = web_future.result()
docs_result = docs_future.result()
return {"web": web_result, "docs": docs_result}
from langgraph.func import entrypoint, task
from langgraph.types import RetryPolicy
@task(retry=RetryPolicy(max_attempts=3, backoff_factor=2.0))
def flaky_api_call(payload: dict) -> dict:
return requests.post(API_URL, json=payload).json()
@entrypoint(checkpointer=InMemorySaver())
def workflow(inputs: dict) -> dict:
result = flaky_api_call(inputs).result()
return {"result": result}
from langgraph.runtime import RunControl
# Choose durability level — trade-off: performance vs crash recovery
control = RunControl(
durability="sync" # "exit" | "async" | "sync"
# exit: fastest, saves only at exit (no mid-run crash recovery)
# async: saves asynchronously (good balance)
# sync: saves before every step (slowest, most durable)
)
from langgraph.types import interrupt, Command
from langgraph.func import entrypoint, task
@task
def get_approval(action: str) -> str:
return interrupt({"prompt": f"Approve: {action}?"})
@entrypoint(checkpointer=InMemorySaver())
def workflow(inputs: dict) -> dict:
decision = get_approval(inputs["action"]).result()
if decision == "yes":
return {"status": "approved"}
return {"status": "rejected"}
# Resume after interrupt
workflow.invoke(
Command(resume="yes"),
config={"configurable": {"thread_id": "1"}},
)
from langgraph.func import entrypoint
from langgraph.checkpoint.memory import InMemorySaver
# Example: wrap a Strands agent
from strands import Agent as StrandsAgent
from strands_tools import http_request
strands_agent = StrandsAgent(tools=[http_request])
@entrypoint(checkpointer=InMemorySaver())
def strands_workflow(inputs: dict) -> dict:
# Your existing agent runs inside @entrypoint
# Gets LangSmith persistence, streaming, HITL for free
result = strands_agent(inputs["prompt"])
return {"output": str(result)}
# Now deployable to LangSmith with full observability
from langgraph.graph import StateGraph, START
from langgraph.func import task
from langgraph.types import RetryPolicy
@task(retry=RetryPolicy(max_attempts=2))
def llm_call(prompt: str) -> str:
return llm.invoke(prompt)
# Use @task inside a StateGraph node
def my_node(state: State) -> State:
# Convert node operations to tasks for granular checkpointing
result = llm_call(state["input"]).result()
return {"output": result}
graph = StateGraph(State)
graph.add_node("my_node", my_node)
# Functional API supports the same stream modes as Graph API
config = {"configurable": {"thread_id": "1"}}
for chunk in my_workflow.stream(inputs, config, stream_mode="updates"):
print(chunk)
for chunk in my_workflow.stream(inputs, config, stream_mode="messages"):
print(chunk) # LLM tokens
| Concept | Decorator/Type | Notes |
|---------|---------------|-------|
| Workflow entry | @entrypoint(checkpointer=...) | Top-level callable; required for persistence |
| Unit of work | @task | Individually checkpointed; retryable |
| Invoke | workflow.invoke(inputs, config) | Blocking call |
| Stream | workflow.stream(inputs, config, stream_mode=...) | Streaming call |
| Parallel | Launch multiple tasks, call .result() to collect | Like asyncio.gather |
| Retry | @task(retry=RetryPolicy(...)) | Per-task retry logic |
| Durability | RunControl(durability="sync\|async\|exit") | Checkpoint frequency |
| Interrupt | interrupt(payload) inside task | Pause for human input |
| Resume | workflow.invoke(Command(resume=value), config) | Continue after interrupt |
| Third-party | Any callable inside @entrypoint | Wrap CrewAI, AutoGen, etc. |
| Need | Use |
|------|-----|
| Explicit graph topology / visualization | Graph API |
| Imperative Python logic | Functional API |
| Wrapping an existing agent | Functional API |
| Named, inspectable stages | Graph API |
| Parallel tasks with dynamic count | Functional API |
| Complex conditional branching | Graph API |
| Minimal boilerplate | Functional API |
| Fan-out with Send | Graph API |
| File | Location |
|------|----------|
| LangGraph Python docs index | ../langgraph/references/llms.md |
| 1473-page corpus summaries | ../langgraph/references/llms-txt.md |
| Full content + all code | ../../langchain-deepagents/references/llms-full.md |
Key doc pages: docs.langchain.com/oss/python/langgraph/functional-api, /use-functional-api, /choosing-apis, /durable-execution
tools
MemPalace local-first AI memory system. Use when setting up persistent memory for Claude Code sessions, mining project files or conversation transcripts, querying past context, configuring MCP tools, managing the knowledge graph, or troubleshooting palace operations.
tools
LangSmith Python SDK — trace, evaluate, and monitor LLM applications. Covers @traceable decorator, trace context manager, Client API, evaluate() / aevaluate(), comparative evaluation, custom evaluators, dataset management, prompt caching, ASGI middleware, and pytest plugin.
development
LangGraph (Python) — build stateful, controllable agent graphs with checkpointing, streaming, persistence, interrupts, fault tolerance, and durable execution. Covers both Graph API (StateGraph) and Functional API (@entrypoint/@task).
development
LangGraph Graph API (Python) — build explicit DAG agent workflows with StateGraph, typed state, nodes, edges, Command routing, Send fan-out, checkpointers, interrupts, and streaming. Use when you need explicit control flow and graph topology.