Skip to content

Commit e801395

Browse files
committed
Update LangGraph samples for temporalio 1.27.0 release
- Drop the [tool.uv.sources] git pin; consume temporalio from PyPI now that 1.27.0 ships the LangGraph plugin. - Keep the protoc CI step around as a permanent fixture so we don't have to add and remove it each time we iterate on a new plugin sample. - Replace dict-comprehension activity_options with explicit per-task literals in the Functional API samples. - Emphasize workflow.wait_condition() in the human-in-the-loop READMEs as the durable wait primitive that pairs with interrupt() and signals. - Clarify that the task result cache is provided by the LangGraph plugin (Temporal), not by upstream LangGraph. - Drop "Same pattern as the Graph API version" cross-references from Functional API workflow docstrings; readers pick one API style. - Tighten the Functional API LangSmith tracing README copy. - Point the parent README to the released contrib package docs.
1 parent f1a305e commit e801395

13 files changed

Lines changed: 94 additions & 59 deletions

File tree

.github/workflows/ci.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ jobs:
3333
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
3434
with:
3535
python-version: ${{ matrix.python }}
36-
# protoc is required to build temporalio from the sdk-python git source
37-
# (see [tool.uv.sources] in pyproject.toml). Drop this step once the SDK
38-
# ships a release that includes the LangGraph plugin.
36+
# protoc is needed whenever uv builds temporalio from a git source
37+
# (e.g. when [tool.uv.sources] pins a branch while a feature is in
38+
# development). Kept on by default so we don't have to add and remove
39+
# this step every time we iterate on a new plugin.
3940
- uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3
4041
with:
4142
version: "23.x"

langgraph_plugin/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# LangGraph Plugin Samples
22

3-
These samples demonstrate the [Temporal LangGraph plugin](https://github.com/temporalio/sdk-python/pull/1448), which runs LangGraph workflows as durable Temporal workflows. Each LangGraph graph node (Graph API) or `@task` (Functional API) executes as a Temporal activity with automatic retries, timeouts, and crash recovery.
3+
These samples demonstrate the [Temporal LangGraph plugin](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/langgraph), which runs LangGraph workflows as durable Temporal workflows. Each LangGraph graph node (Graph API) or `@task` (Functional API) executes as a Temporal activity with automatic retries, timeouts, and crash recovery.
44

55
Samples are organized by API style:
66

@@ -70,4 +70,4 @@ uv run langgraph_plugin/<api>/langsmith_tracing/main.py
7070

7171
## Related
7272

73-
- [SDK PR: LangGraph plugin](https://github.com/temporalio/sdk-python/pull/1448)
73+
- [Temporal LangGraph plugin docs](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/langgraph)

langgraph_plugin/functional_api/continue_as_new/README.md

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

3-
Demonstrates combining Temporal's continue-as-new with LangGraph's task result caching to avoid re-executing completed `@task` functions across workflow boundaries.
3+
Demonstrates combining Temporal's continue-as-new with the LangGraph plugin's task result cache to avoid re-executing completed `@task` functions across workflow boundaries.
44

55
## What This Sample Demonstrates
66

langgraph_plugin/functional_api/continue_as_new/workflow.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
"""Continue-as-new with caching using the LangGraph Functional API with Temporal.
22
3-
Demonstrates Temporal's continue-as-new with LangGraph's task result caching
4-
to avoid re-executing completed @task functions across workflow boundaries.
3+
Demonstrates Temporal's continue-as-new with the LangGraph plugin's task
4+
result cache to avoid re-executing completed @task functions across
5+
workflow boundaries.
56
"""
67

78
from dataclasses import dataclass
@@ -41,14 +42,21 @@ async def pipeline_entrypoint(data: int) -> dict:
4142
return {"result": tripled}
4243

4344

44-
all_tasks: list[Any] = [double, add_50, triple]
45+
all_tasks = [double, add_50, triple]
4546

4647
activity_options = {
47-
t.func.__name__: {
48+
"double": {
4849
"execute_in": "activity",
4950
"start_to_close_timeout": timedelta(seconds=30),
50-
}
51-
for t in all_tasks
51+
},
52+
"add_50": {
53+
"execute_in": "activity",
54+
"start_to_close_timeout": timedelta(seconds=30),
55+
},
56+
"triple": {
57+
"execute_in": "activity",
58+
"start_to_close_timeout": timedelta(seconds=30),
59+
},
5260
}
5361

5462

langgraph_plugin/functional_api/control_flow/workflow.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
"""
88

99
from datetime import timedelta
10-
from typing import Any
1110

1211
from langgraph.func import entrypoint, task
1312
from temporalio import workflow
@@ -75,7 +74,7 @@ async def control_flow_pipeline(items: list[str]) -> dict:
7574
return {"results": results, "summary": summary_text, "total": len(results)}
7675

7776

78-
all_tasks: list[Any] = [
77+
all_tasks = [
7978
validate_item,
8079
classify_item,
8180
process_urgent,
@@ -84,11 +83,26 @@ async def control_flow_pipeline(items: list[str]) -> dict:
8483
]
8584

8685
activity_options = {
87-
t.func.__name__: {
86+
"validate_item": {
8887
"execute_in": "activity",
8988
"start_to_close_timeout": timedelta(seconds=30),
90-
}
91-
for t in all_tasks
89+
},
90+
"classify_item": {
91+
"execute_in": "activity",
92+
"start_to_close_timeout": timedelta(seconds=30),
93+
},
94+
"process_urgent": {
95+
"execute_in": "activity",
96+
"start_to_close_timeout": timedelta(seconds=30),
97+
},
98+
"process_normal": {
99+
"execute_in": "activity",
100+
"start_to_close_timeout": timedelta(seconds=30),
101+
},
102+
"summarize": {
103+
"execute_in": "activity",
104+
"start_to_close_timeout": timedelta(seconds=30),
105+
},
92106
}
93107

94108

langgraph_plugin/functional_api/human_in_the_loop/README.md

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

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.
3+
Demonstrates pausing an entrypoint with LangGraph's `interrupt()` and waiting indefinitely for human review with Temporal's `workflow.wait_condition()`. A Temporal signal delivers the human's feedback; a Temporal query exposes the pending draft to UIs.
44

55
## What This Sample Demonstrates
66

7-
- Using `interrupt()` inside a `@task` to pause for human input
8-
- Temporal signals and queries for asynchronous human feedback
7+
- `workflow.wait_condition()` to block the Workflow until human input arrives — for as long as it takes, with no polling and no timeout
8+
- `interrupt()` inside a `@task` to pause the entrypoint at the review point
9+
- Temporal **signals** to deliver human feedback and **queries** to expose the pending draft
910
- Resuming with `Command(resume=...)` via the v2 API
1011
- Setting a checkpointer on the entrypoint for interrupt/resume support
1112

1213
## How It Works
1314

1415
1. The `generate_draft` task produces a draft response.
1516
2. The `request_human_review` task calls `interrupt(draft)`, pausing the entrypoint.
16-
3. The workflow stores the draft and waits for a signal.
17-
4. After receiving feedback, the entrypoint resumes and returns the result.
17+
3. The Workflow stores the draft (visible via the query) and calls `workflow.wait_condition()` — blocking durably until the signal sets `_human_input`. This can wait indefinitely; Temporal persists the state.
18+
4. After the signal arrives, the entrypoint resumes with `Command(resume=...)` and returns the final response.
1819

1920
## Running the Sample
2021

langgraph_plugin/functional_api/human_in_the_loop/workflow.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
"""Human-in-the-loop chatbot using the LangGraph Functional API with Temporal.
22
3-
Same pattern as the Graph API version, but using @task and @entrypoint decorators.
3+
The @entrypoint pauses at interrupt(); the Workflow waits indefinitely with
4+
workflow.wait_condition() until a Temporal signal delivers human feedback,
5+
then resumes the entrypoint with Command(resume=...).
46
"""
57

68
from datetime import timedelta
@@ -40,14 +42,17 @@ async def chatbot_entrypoint(user_message: str) -> dict:
4042
return {"response": final_response}
4143

4244

43-
all_tasks: list[Any] = [generate_draft, request_human_review]
45+
all_tasks = [generate_draft, request_human_review]
4446

4547
activity_options = {
46-
t.func.__name__: {
48+
"generate_draft": {
4749
"execute_in": "activity",
4850
"start_to_close_timeout": timedelta(seconds=30),
49-
}
50-
for t in all_tasks
51+
},
52+
"request_human_review": {
53+
"execute_in": "activity",
54+
"start_to_close_timeout": timedelta(seconds=30),
55+
},
5156
}
5257

5358

langgraph_plugin/functional_api/langsmith_tracing/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# LangSmith Tracing (Functional API)
22

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.
3+
Demonstrates combining `LangGraphPlugin` (durable task execution) with Temporal's `LangSmithPlugin` for full tracing of LLM calls through Temporal workflows, using LangGraph's `@task` and `@entrypoint` decorators.
44

55
## What This Sample Demonstrates
66

langgraph_plugin/functional_api/react_agent/workflow.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
"""ReAct agent using the LangGraph Functional API with Temporal.
22
3-
Same pattern as the Graph API version, but using @task and @entrypoint.
4-
The Functional API naturally expresses the ReAct loop as a while loop,
5-
making the control flow explicit and easy to extend.
3+
The Functional API expresses the ReAct loop as a plain `while` loop, making
4+
the control flow explicit and easy to extend.
65
"""
76

87
from datetime import timedelta
9-
from typing import Any
108

119
from langgraph.func import entrypoint, task
1210
from temporalio import workflow
@@ -69,14 +67,17 @@ async def react_agent_entrypoint(query: str) -> dict:
6967
history.append(result)
7068

7169

72-
all_tasks: list[Any] = [agent_think, execute_tool]
70+
all_tasks = [agent_think, execute_tool]
7371

7472
activity_options = {
75-
t.func.__name__: {
73+
"agent_think": {
7674
"execute_in": "activity",
7775
"start_to_close_timeout": timedelta(seconds=30),
78-
}
79-
for t in all_tasks
76+
},
77+
"execute_tool": {
78+
"execute_in": "activity",
79+
"start_to_close_timeout": timedelta(seconds=30),
80+
},
8081
}
8182

8283

langgraph_plugin/graph_api/continue_as_new/README.md

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

3-
Demonstrates Temporal's continue-as-new with LangGraph's task result caching to avoid re-executing completed graph nodes across workflow boundaries.
3+
Demonstrates combining Temporal's continue-as-new with the LangGraph plugin's task result cache to avoid re-executing completed graph nodes across workflow boundaries.
44

55
## What This Sample Demonstrates
66

77
- Using `workflow.continue_as_new()` to reset event history for long-running pipelines
8-
- Capturing task results with `cache()` before continuing
8+
- Capturing node results with `cache()` before continuing
99
- Restoring cached results with `temporal_graph(name, cache=...)` so completed nodes are skipped
1010
- Each node executes exactly once despite multiple workflow invocations
1111

0 commit comments

Comments
 (0)