DS DevShelfHub Projects · AI tools
Tutorials / LangChain / Reference / Decorators / @task
Decorator langgraph.func

@task: Reference Guide

By DevShelfHub

Mark function as cacheable task in workflow.

What is @task?

@task is a LangGraph decorator that wraps a Python function as a cacheable, async-compatible task inside an @entrypoint workflow. When an @entrypoint function calls a @task-decorated function, LangGraph does not execute it immediately — it schedules it as a future and returns a Future-like object. Calling .result() on that object blocks until the task completes, while submitting multiple task futures before calling .result() on any of them causes them to run concurrently.

The caching behavior is the key feature: if the same @task function is called with the same arguments within the same thread, LangGraph returns the cached result from the checkpoint rather than re-executing the function. This is essential for interrupt-and-resume workflows — when a human reviews state and resumes the @entrypoint, expensive tasks (LLM calls, API requests, database queries) that already ran are replayed from cache rather than re-executed. This prevents double-billing on LLM API calls and keeps resume latency low.

Because caching is input-based, @task functions must be deterministic — the same input must always produce the same output. Non-deterministic functions (those using random(), datetime.now() without a seed, or relying on mutable global state) will serve stale cached results on resume, causing subtle bugs. Side-effecting functions (writing to a database, sending an email) are also problematic — on resume the cached result is returned but the side effect does not re-run, which can leave external systems in an inconsistent state. Use @task for pure computation and I/O-read operations; keep writes and side effects outside @task or gate them with a flag in state.

Use Cases

  • Cache API calls
  • Cache DB queries
  • Cache LLM results
  • Cache processing
  • Parallel tasks
  • Cost optimization

Key Features

  • Auto caching
  • TTL support
  • Multiple backends
  • Deterministic
  • Task naming
  • Cost reduction

When NOT to Use

For non-deterministic functions or side effects.

Notes

Tasks must be deterministic — non-deterministic functions serve stale cache

@task caches on (function_name, args) key. If your function uses random(), time-based logic, or reads from mutable global state, resume workflows will receive the cached (stale) result instead of a fresh one. Any task that must produce different output each time (e.g., generating a UUID) should not be decorated with @task.

Side effects do not re-run on resume — guard writes with state flags

If a @task function sends an email or writes to a database, the side effect ran during the original execution and is recorded in the cache. On resume, the cached result is returned but the email/write does not happen again. For idempotent writes this is fine; for one-time side effects, move the write outside the @task or check a "sent" flag in state before running.

Submit futures before calling .result() to run tasks in parallel

fut1 = task_a(x); fut2 = task_b(y); a = fut1.result(); b = fut2.result() — both tasks start concurrently. Calling fut1.result() before submitting task_b serializes them. Always submit all the tasks you want to parallelize before blocking on any .result() call.

The name parameter affects cache key disambiguation

If you rename a @task function or have two functions with the same name in different modules, use @task(name="unique-id") to set an explicit cache key name. This prevents cache collisions and ensures that renaming a function mid-workflow does not invalidate all existing checkpoints.

Import

python
from langgraph.func import task

How to Apply

python
@task
def process_step(data):
    return transformed_data

Parameters

Parameter Type Default Purpose
name str function name Task name

What It Enables

  • Result caching
  • TTL expiration
  • Cost reduction
  • Deterministic execution

Code Examples

Basic cacheable task

python
from langgraph.func import task
@task
def fetch(url: str) -> dict:
    return requests.get(url).json()

Parallel task execution inside @entrypoint

python
from langgraph.func import entrypoint, task
@task
def embed(text: str) -> list:
    return embeddings.embed_query(text)
@task
def retrieve(query: str) -> list:
    return vector_store.similarity_search(query, k=5)
@entrypoint
def pipeline(question: str) -> str:
    # Submit both tasks — they run concurrently
    embed_fut = embed(question)
    retrieve_fut = retrieve(question)
    q_embedding = embed_fut.result()
    docs = retrieve_fut.result()
    return summarize(docs)

Cache LLM call to prevent double-billing on resume

python
from langgraph.func import task
from langchain_openai import ChatOpenAI
model = ChatOpenAI(model="gpt-4o-mini")
@task
def classify(text: str) -> str:
    response = model.invoke([HumanMessage(content=f"Classify: {text}")])
    return response.content
# On resume after interrupt, classify() result is served from cache
# — no second LLM API call is made

Integration Patterns

@task within @entrypoint
graph.compile()

Common Mistakes

❌ @task def fn(): return random.random() # Non-deterministic

✅ @task def fn(seed): return deterministic(seed)

Browse the full LangChain API reference index to explore more classes, methods, and decorators, or start with the LangChain introduction tutorial for end-to-end context on building with @task and the wider framework.

@task FAQ

What does @task do in LangChain?

Mark function as cacheable task in workflow. @task is a LangGraph decorator that wraps a Python function as a cacheable, async-compatible task inside an @entrypoint workflow. When an @entrypoint function calls a @task-decorated function, LangGraph does not execute it immediately — it schedules it as a future and returns a Future-like object. Calling .result() on that object blocks until the task completes, while submitting multiple task futures before calling .result() on any of them causes them to run concurrently. Th…

Which package provides @task?

DevShelfHub documents @task from the langgraph.func package. Pin your installed LangChain version and match imports to the snippet on this page.

When should I use @task?

Use @task when your LangChain agents, workflows, or pipelines need the behavior described in this guide.

When should I avoid using @task?

For non-deterministic functions or side effects.

How do I apply @task in Python?

Apply @task as a decorator above your function definition. Import it from from langgraph.func import task and annotate the function you want to wrap. See the code examples on this page for a complete working snippet.

Where can I explore more LangChain API reference pages?

Open the LangChain API reference index on DevShelfHub to browse classes, methods, and decorators, each with runnable examples, parameters, common mistakes, and cross-links.