Skip to content

Commit f1a305e

Browse files
committed
Address review feedback on LangGraph samples
- Drop cross-references between Functional API and Graph API READMEs so each stands alone (review comment 1) - Combine run_worker.py + run_workflow.py into a single main.py for the langsmith_tracing samples to reduce setup steps (review comment 2) - Fix workflow -> Workflow casing (review comment 3) - Alias temporalio's entrypoint and graph helpers as temporal_entrypoint / temporal_graph at import sites to avoid the langgraph.func.entrypoint collision (review comment 4) - Demonstrate @Traceable in three places in both langsmith_tracing samples: on the Activity/task itself, on a helper called from the Activity, and on a helper called from the Workflow (review comment 5) - Drop unnecessary single-task list comprehension for activity_options in hello_world and langsmith_tracing functional samples (review comment 6) - Spell out 'temporal server start-dev' in every sample README's prerequisites (review comment 7) - Fix stale README references to get_cache() now that the API is cache() (review comment 8) - Rename arbitrarily-named ETL pipeline functions in continue_as_new to honest math names (double / add_50 / triple) per review comment 9
1 parent 876892f commit f1a305e

27 files changed

Lines changed: 186 additions & 212 deletions

File tree

langgraph_plugin/README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ Samples are organized by API style:
3434

3535
## Running a Sample
3636

37-
Each sample has two scripts -- start the worker first, then the workflow starter in a separate terminal.
37+
Most samples have two scripts -- start the Worker first, then the Workflow starter in a separate terminal.
3838

3939
```bash
40-
# Terminal 1: start the worker
40+
# Terminal 1: start the Worker
4141
uv run langgraph_plugin/<api>/<sample>/run_worker.py
4242

43-
# Terminal 2: start the workflow
43+
# Terminal 2: start the Workflow
4444
uv run langgraph_plugin/<api>/<sample>/run_workflow.py
4545
```
4646

@@ -54,11 +54,17 @@ uv run langgraph_plugin/graph_api/human_in_the_loop/run_worker.py
5454
uv run langgraph_plugin/graph_api/human_in_the_loop/run_workflow.py
5555
```
5656

57+
The LangSmith Tracing samples bundle the Worker and Workflow execution into a single `main.py`:
58+
59+
```bash
60+
uv run langgraph_plugin/<api>/langsmith_tracing/main.py
61+
```
62+
5763
## Key Features Demonstrated
5864

5965
- **Durable execution** -- Every graph node / `@task` runs as a Temporal activity with configurable timeouts and retry policies.
6066
- **Human-in-the-loop** -- LangGraph's `interrupt()` pauses the graph; Temporal signals deliver human input; queries expose pending state to UIs.
61-
- **Continue-as-new with caching** -- `get_cache()` captures completed task results; passing the cache to the next execution avoids re-running them.
67+
- **Continue-as-new with caching** -- `cache()` captures completed task results; passing the cache to the next execution avoids re-running them.
6268
- **Conditional routing** -- Graph API's `add_conditional_edges` and Functional API's native `if/else`/`while` for agent loops.
6369
- **Parallel execution** -- Functional API launches multiple tasks concurrently by creating futures before awaiting them.
6470

langgraph_plugin/functional_api/continue_as_new/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
# Continue-as-New with Caching (Functional API)
22

3-
Same pattern as the Graph API version, using `@task` and `@entrypoint` decorators.
3+
Demonstrates combining Temporal's continue-as-new with LangGraph's task result caching to avoid re-executing completed `@task` functions across workflow boundaries.
44

55
## What This Sample Demonstrates
66

7-
- Task result caching across continue-as-new boundaries with `get_cache()`
7+
- Task result caching across continue-as-new boundaries with `cache()`
88
- Restoring cached results with `entrypoint(name, cache=...)`
99
- Each `@task` executes exactly once despite multiple workflow invocations
1010

1111
## How It Works
1212

13-
1. Three tasks run sequentially: `extract` (x2) -> `transform` (+50) -> `load` (x3).
13+
1. Three tasks run sequentially: `double` (x2) -> `add_50` (+50) -> `triple` (x3).
1414
2. After the first invocation, the workflow continues-as-new with the cache.
1515
3. On subsequent invocations, all tasks return cached results instantly.
1616
4. Input 10 -> 20 -> 70 -> 210.
1717

1818
## Running the Sample
1919

20-
Prerequisites: `uv sync --group langgraph` and a running Temporal dev server.
20+
Prerequisites: `uv sync --group langgraph` and a running Temporal dev server (`temporal server start-dev`).
2121

2222
```bash
2323
# Terminal 1
@@ -32,5 +32,5 @@ uv run langgraph_plugin/functional_api/continue_as_new/run_workflow.py
3232
| File | Description |
3333
|------|-------------|
3434
| `workflow.py` | `@task` functions, `@entrypoint`, `PipelineInput`, and `PipelineFunctionalWorkflow` |
35-
| `run_worker.py` | Registers tasks and entrypoint with `LangGraphPlugin`, starts worker |
36-
| `run_workflow.py` | Executes the pipeline workflow and prints the result |
35+
| `run_worker.py` | Registers tasks and entrypoint with `LangGraphPlugin`, starts Worker |
36+
| `run_workflow.py` | Executes the pipeline Workflow and prints the result |

langgraph_plugin/functional_api/continue_as_new/workflow.py

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,47 @@
11
"""Continue-as-new with caching using the LangGraph Functional API with Temporal.
22
3-
Same pattern as the Graph API version, but using @task and @entrypoint decorators.
3+
Demonstrates Temporal's continue-as-new with LangGraph's task result caching
4+
to avoid re-executing completed @task functions across workflow boundaries.
45
"""
56

67
from dataclasses import dataclass
78
from datetime import timedelta
89
from typing import Any
910

10-
from langgraph.func import entrypoint as lg_entrypoint
11-
from langgraph.func import task
11+
from langgraph.func import entrypoint, task
1212
from temporalio import workflow
13-
from temporalio.contrib.langgraph import cache, entrypoint
13+
from temporalio.contrib.langgraph import cache
14+
from temporalio.contrib.langgraph import entrypoint as temporal_entrypoint
1415

1516

1617
@task
17-
def extract(data: int) -> int:
18-
"""Stage 1: Extract -- simulate data extraction by doubling the input."""
18+
def double(data: int) -> int:
19+
"""Stage 1: double the input."""
1920
return data * 2
2021

2122

2223
@task
23-
def transform(data: int) -> int:
24-
"""Stage 2: Transform -- simulate transformation by adding 50."""
24+
def add_50(data: int) -> int:
25+
"""Stage 2: add 50."""
2526
return data + 50
2627

2728

2829
@task
29-
def load(data: int) -> int:
30-
"""Stage 3: Load -- simulate loading by tripling the result."""
30+
def triple(data: int) -> int:
31+
"""Stage 3: triple the result."""
3132
return data * 3
3233

3334

34-
@lg_entrypoint()
35+
@entrypoint()
3536
async def pipeline_entrypoint(data: int) -> dict:
36-
"""Run the 3-stage pipeline: extract -> transform -> load."""
37-
extracted = await extract(data)
38-
transformed = await transform(extracted)
39-
loaded = await load(transformed)
40-
return {"result": loaded}
37+
"""Run the 3-stage pipeline: double -> add_50 -> triple."""
38+
doubled = await double(data)
39+
plus_50 = await add_50(doubled)
40+
tripled = await triple(plus_50)
41+
return {"result": tripled}
4142

4243

43-
all_tasks: list[Any] = [extract, transform, load]
44+
all_tasks: list[Any] = [double, add_50, triple]
4445

4546
activity_options = {
4647
t.func.__name__: {
@@ -68,7 +69,7 @@ class PipelineFunctionalWorkflow:
6869

6970
@workflow.run
7071
async def run(self, input_data: PipelineInput) -> dict[str, Any]:
71-
app = entrypoint("pipeline", cache=input_data.cache)
72+
app = temporal_entrypoint("pipeline", cache=input_data.cache)
7273
result = await app.ainvoke(input_data.data)
7374

7475
if input_data.phase < 3:

langgraph_plugin/functional_api/control_flow/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Demonstrates the Functional API's strength for complex control flow: parallel ex
1818

1919
## Running the Sample
2020

21-
Prerequisites: `uv sync --group langgraph` and a running Temporal dev server.
21+
Prerequisites: `uv sync --group langgraph` and a running Temporal dev server (`temporal server start-dev`).
2222

2323
```bash
2424
# Terminal 1

langgraph_plugin/functional_api/control_flow/workflow.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@
99
from datetime import timedelta
1010
from typing import Any
1111

12-
from langgraph.func import entrypoint as lg_entrypoint
13-
from langgraph.func import task
12+
from langgraph.func import entrypoint, task
1413
from temporalio import workflow
15-
from temporalio.contrib.langgraph import entrypoint
14+
from temporalio.contrib.langgraph import entrypoint as temporal_entrypoint
1615

1716

1817
@task
@@ -49,7 +48,7 @@ def summarize(results: list[str]) -> str:
4948
)
5049

5150

52-
@lg_entrypoint()
51+
@entrypoint()
5352
async def control_flow_pipeline(items: list[str]) -> dict:
5453
"""Process a batch of items with parallel validation, sequential
5554
classification, and conditional routing.
@@ -97,4 +96,4 @@ async def control_flow_pipeline(items: list[str]) -> dict:
9796
class ControlFlowWorkflow:
9897
@workflow.run
9998
async def run(self, items: list[str]) -> dict:
100-
return await entrypoint("control-flow").ainvoke(items)
99+
return await temporal_entrypoint("control-flow").ainvoke(items)

langgraph_plugin/functional_api/hello_world/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ The simplest possible LangGraph Functional API + Temporal sample: a single `@tas
1010

1111
## Running the Sample
1212

13-
Prerequisites: `uv sync --group langgraph` and a running Temporal dev server.
13+
Prerequisites: `uv sync --group langgraph` and a running Temporal dev server (`temporal server start-dev`).
1414

1515
```bash
1616
# Terminal 1

langgraph_plugin/functional_api/hello_world/workflow.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@
44
"""
55

66
from datetime import timedelta
7-
from typing import Any
87

9-
from langgraph.func import entrypoint as lg_entrypoint
10-
from langgraph.func import task
8+
from langgraph.func import entrypoint, task
119
from temporalio import workflow
12-
from temporalio.contrib.langgraph import entrypoint
10+
from temporalio.contrib.langgraph import entrypoint as temporal_entrypoint
1311

1412

1513
@task
@@ -18,26 +16,25 @@ def process_query(query: str) -> str:
1816
return f"Processed: {query}"
1917

2018

21-
@lg_entrypoint()
19+
@entrypoint()
2220
async def hello_entrypoint(query: str) -> dict:
2321
"""Process the query and return it in a result dict."""
2422
result = await process_query(query)
2523
return {"result": result}
2624

2725

28-
all_tasks: list[Any] = [process_query]
26+
all_tasks = [process_query]
2927

3028
activity_options = {
31-
t.func.__name__: {
29+
"process_query": {
3230
"execute_in": "activity",
3331
"start_to_close_timeout": timedelta(seconds=10),
34-
}
35-
for t in all_tasks
32+
},
3633
}
3734

3835

3936
@workflow.defn
4037
class HelloWorldFunctionalWorkflow:
4138
@workflow.run
4239
async def run(self, query: str) -> dict:
43-
return await entrypoint("hello-world").ainvoke(query)
40+
return await temporal_entrypoint("hello-world").ainvoke(query)

langgraph_plugin/functional_api/human_in_the_loop/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Human-in-the-Loop Chatbot (Functional API)
22

3-
Same pattern as the Graph API version, but using `@task` and `@entrypoint` decorators for an imperative programming style.
3+
Demonstrates using LangGraph's `interrupt()` to pause an entrypoint for human review, combined with Temporal signals and queries for asynchronous feedback, using the imperative `@task`/`@entrypoint` style.
44

55
## What This Sample Demonstrates
66

@@ -18,7 +18,7 @@ Same pattern as the Graph API version, but using `@task` and `@entrypoint` decor
1818

1919
## Running the Sample
2020

21-
Prerequisites: `uv sync --group langgraph` and a running Temporal dev server.
21+
Prerequisites: `uv sync --group langgraph` and a running Temporal dev server (`temporal server start-dev`).
2222

2323
```bash
2424
# Terminal 1

langgraph_plugin/functional_api/human_in_the_loop/workflow.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@
88

99
from langchain_core.runnables import RunnableConfig
1010
from langgraph.checkpoint.memory import InMemorySaver
11-
from langgraph.func import entrypoint as lg_entrypoint
12-
from langgraph.func import task
11+
from langgraph.func import entrypoint, task
1312
from langgraph.types import Command, interrupt
1413
from temporalio import workflow
15-
from temporalio.contrib.langgraph import entrypoint
14+
from temporalio.contrib.langgraph import entrypoint as temporal_entrypoint
1615

1716

1817
@task
@@ -33,7 +32,7 @@ def request_human_review(draft: str) -> str:
3332
return f"[Revised] {draft} (incorporating feedback: {feedback})"
3433

3534

36-
@lg_entrypoint()
35+
@entrypoint()
3736
async def chatbot_entrypoint(user_message: str) -> dict:
3837
"""Chatbot entrypoint: generate a draft, get human review, return result."""
3938
draft = await generate_draft(user_message)
@@ -70,7 +69,7 @@ def get_draft(self) -> str | None:
7069

7170
@workflow.run
7271
async def run(self, user_message: str) -> dict[str, Any]:
73-
app = entrypoint("chatbot")
72+
app = temporal_entrypoint("chatbot")
7473
app.checkpointer = InMemorySaver()
7574
config = RunnableConfig(
7675
{"configurable": {"thread_id": workflow.info().workflow_id}}
Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,30 @@
11
# LangSmith Tracing (Functional API)
22

3-
Same pattern as the Graph API version, using `@task` and `@entrypoint` decorators.
3+
Demonstrates combining `LangGraphPlugin` (durable task execution) with Temporal's `LangSmithPlugin` (observability) for full tracing of LLM calls through Temporal workflows, using LangGraph's `@task` and `@entrypoint` decorators.
44

55
## What This Sample Demonstrates
66

7-
- Combining `LangSmithPlugin` (observability) with `LangGraphPlugin` (durability)
8-
- `@traceable` decorator on a `@task` for LangSmith tracing of LLM calls
9-
- Both plugins working together in the Functional API style
7+
- Using `LangSmithPlugin` on the Temporal client for automatic trace propagation
8+
- Using `LangGraphPlugin` on the Worker for durable LangGraph execution
9+
- `@traceable` in three places: on the `@task` (Activity) itself, on a helper called from inside the `@task`, and on a helper called from inside the `@entrypoint` (Workflow)
10+
- Both plugins working together: durability + observability
1011

1112
## How It Works
1213

1314
1. The Temporal client is created with `LangSmithPlugin(add_temporal_runs=True)`.
14-
2. The worker registers the `chat` task with `LangGraphPlugin`.
15-
3. When the workflow runs, the `chat` task executes as a Temporal activity.
16-
4. The `@traceable` decorator sends trace data to LangSmith.
15+
2. A Worker registers the `chat` task with `LangGraphPlugin`.
16+
3. When the Workflow runs, the `chat` task executes as a Temporal Activity.
17+
4. `@traceable` decorators emit trace data to LangSmith for the task, an in-task helper, and an in-entrypoint helper.
1718

1819
## Running the Sample
1920

20-
Prerequisites: `uv sync --group langgraph` and a running Temporal dev server.
21+
Prerequisites: `uv sync --group langgraph` and a running Temporal dev server (`temporal server start-dev`).
2122

2223
```bash
2324
export ANTHROPIC_API_KEY='your-key'
2425
export LANGCHAIN_API_KEY='your-key'
2526

26-
# Terminal 1
27-
uv run langgraph_plugin/functional_api/langsmith_tracing/run_worker.py
28-
29-
# Terminal 2
30-
uv run langgraph_plugin/functional_api/langsmith_tracing/run_workflow.py
27+
uv run langgraph_plugin/functional_api/langsmith_tracing/main.py
3128
```
3229

3330
Traces will appear in your [LangSmith](https://smith.langchain.com/) dashboard.
@@ -36,6 +33,5 @@ Traces will appear in your [LangSmith](https://smith.langchain.com/) dashboard.
3633

3734
| File | Description |
3835
|------|-------------|
39-
| `workflow.py` | `@traceable` chat task, `@entrypoint`, and `ChatFunctionalWorkflow` |
40-
| `run_worker.py` | Creates client with `LangSmithPlugin`, worker with `LangGraphPlugin` |
41-
| `run_workflow.py` | Creates client with `LangSmithPlugin`, executes workflow |
36+
| `workflow.py` | `@traceable` chat task + helpers, `@entrypoint`, and `ChatFunctionalWorkflow` |
37+
| `main.py` | Starts a Worker and executes the Workflow in a single process |

0 commit comments

Comments
 (0)