Compare commits

...
Author SHA1 Message Date
Eugene YurtsevandHunter Lovell d1d4abf70e x 2025-07-28 14:21:55 -07:00
Sydney RunkleandGitHub fadbe7d710 fix(docs): clarify value of context (#5689) 2025-07-28 16:38:02 -04:00
Sydney Runkle c861614337 Merge branch 'sr/more-context-for-context' of https://github.com/langchain-ai/langgraph into sr/more-context-for-context 2025-07-28 16:34:54 -04:00
Sydney Runkle c020f01425 final nits 2025-07-28 16:34:13 -04:00
14949c81c8 Apply suggestions from code review
Co-authored-by: Lauren Hirata Singh <lauren@langchain.dev>
2025-07-28 16:22:16 -04:00
Sydney Runkle 3af857922a formatting for bullets 2025-07-28 16:19:27 -04:00
Sydney Runkle 7ec049e0c7 note on window 2025-07-28 16:15:56 -04:00
Sydney Runkle 1923ff8d85 first pass 2025-07-28 16:15:14 -04:00
Sydney RunkleandGitHub 4b9b7d0b1c fix(docs): better docs for resuming multiple interrupts (#5688) 2025-07-28 16:05:22 -04:00
624247a51f Update docs/docs/agents/context.md
Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2025-07-28 15:31:36 -04:00
Sydney Runkle b21b595927 Merge branch 'sr/more-docs' of https://github.com/langchain-ai/langgraph into sr/more-docs 2025-07-28 15:21:24 -04:00
Sydney Runkle f4633a0015 single example 2025-07-28 15:20:32 -04:00
Sam CrowderandGitHub 86017c010c docs: [LangGraph Server Changelog Bot] Changelog updates for new version(s) (#5686) 2025-07-28 12:17:20 -07:00
Sydney Runkle 2115cffc94 notes on context 2025-07-28 15:17:05 -04:00
03726f9bc6 Update docs/docs/how-tos/human_in_the_loop/add-human-in-the-loop.md
Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2025-07-28 15:14:37 -04:00
Sydney Runkle 509dfd1f21 better hitl multi interrupt resume docs 2025-07-28 15:05:57 -04:00
Sam Crowder efca21070d Update changelog via LangGraph Server Changelog Bot 2025-07-28 10:10:50 -07:00
6 changed files with 85 additions and 22 deletions
+10 -5
View File
@@ -310,6 +310,12 @@ def _highlight_code_blocks(markdown: str) -> str:
return markdown
TARGET_LANGUAGE = os.environ.get("TARGET_LANGUAGE", "python")
if TARGET_LANGUAGE not in {"python", "js"}:
raise ValueError(f"TARGET_LANGUAGE must be 'python' or 'js', got {TARGET_LANGUAGE}")
def _on_page_markdown_with_config(
markdown: str,
page: Page,
@@ -332,16 +338,15 @@ def _on_page_markdown_with_config(
markdown = _highlight_code_blocks(markdown)
# Apply conditional rendering for code blocks
target_language = kwargs.get("target_language", "python")
markdown = _apply_conditional_rendering(markdown, target_language)
if target_language == "js":
markdown = _apply_conditional_rendering(markdown, TARGET_LANGUAGE)
if TARGET_LANGUAGE == "js":
markdown = _resolve_cross_references(markdown, JS_LINK_MAP)
elif target_language == "python":
elif TARGET_LANGUAGE == "python":
# Via a dedicated plugin
pass
else:
raise ValueError(
f"Unsupported target language: {target_language}. "
f"Unsupported target language: {TARGET_LANGUAGE}. "
"Supported languages are 'python' and 'js'."
)
+13 -6
View File
@@ -8,7 +8,7 @@ Context includes *any* data outside the message list that can shape behavior. Th
- Internal state updated during a multi-step reasoning process.
- Persistent memory or facts from previous interactions.
LangGraph provides **three** primary ways to supply context:
LangGraph provides **three** primary ways to manage context:
| Type | Description | Mutable? | Lifetime |
|------------------------------------------------------------------------------|-----------------------------------------------|----------|-------------------------|
@@ -18,14 +18,21 @@ LangGraph provides **three** primary ways to supply context:
### Runtime Context
!!! note "`config['configurable']` -> `runtime.context`"
Runtime context is for immutable data like user metadata, tools, db connections, etc. Use this when you have values that don't change mid-run.
In LangGraph < v1.0, static runtime context was passed via the `config['configurable']` key, paired with a `config_schema` argument
to `StateGraph` or `Pregel`. This is now deprecated and will be removed in v2.0.
!!! version-added "New in LangGraph v0.6: `Runtime.context` replaces `config['configurable']`"
As of LangGraph v1.0, the Runtime object is recommended to access static context and runtime-specific information like the store and stream writer.
The `Runtime` object is recommended to access static context and runtime-specific information like the store and stream writer.
Runtime context is for immutable data like user metadata or API keys. Use this when you have values that don't change mid-run.
!!! note
Runtime context refers to local context: data and dependencies your code needs to run. It does not refer to:
* The LLM context, which is the data passed into the LLM's prompt.
* The "context window", which is the maximum number of tokens that can be passed to the LLM.
You likely want to use the local context to optimize the LLM's context window. For example, you
could use a user id to fetch a user's name and information from a database to populate the context window with relevant memories.
Specify static context via the `context` argument to `invoke` / `stream`, which is reserved for this purpose:
@@ -4,6 +4,9 @@
---
## v0.2.109 (2025-07-28)
- Fixed an issue where missing config schema occurred when `config_type` was not set.
## v0.2.108 (2025-07-28)
- Added compatibility for langgraph v0.6, including new context API support and a migration to enhance context handling in assistant operations.
+1 -1
View File
@@ -28,7 +28,7 @@ To review, edit, and approve tool calls in an agent or workflow, [use LangGraph'
There are two ways to pause a graph:
- [Dynamic interrupts](../how-tos/human_in_the_loop/add-human-in-the-loop.md#pause-using-interrupt): Use `interrupt` to pause a graph from inside a specific node, based on the current state of the graph.
- [Static interrupts](../how-tos/human_in_the_loop/add-human-in-the-loop.md#debug-with-interrupts): Use `interrupt_before` and `interrupt_after` to pause the graph at defined points, either before or after a node executes.
- [Static interrupts](../how-tos/human_in_the_loop/add-human-in-the-loop.md#debug-with-interrupts): Use `interrupt_before` and `interrupt_after` to pause the graph at pre-defined points, either before or after a node executes.
<figure markdown="1">
![image](./img/breakpoints.png){: style="max-height:400px"}
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

@@ -128,7 +128,7 @@ print(graph.invoke(Command(resume="Edited text"), config=config)) # (7)!
!!! tip "New in 0.4.0"
`__interrupt__` is a special key that will be returned when running the graph if the graph is interrupted. Support for `__interrupt__` in `invoke` and `ainvoke` has been added in version 0.4.0. If you're on an older version, you will only see `__interrupt__` in the result if you use `stream` or `astream`. You can also use `graph.get_state(thread_id)` to get the interrupt value.
`__interrupt__` is a special key that will be returned when running the graph if the graph is interrupted. Support for `__interrupt__` in `invoke` and `ainvoke` has been added in version 0.4.0. If you're on an older version, you will only see `__interrupt__` in the result if you use `stream` or `astream`. You can also use `graph.get_state(thread_id)` to get the interrupt value(s).
!!! warning
@@ -145,19 +145,67 @@ To resume execution, use the [`Command`][langgraph.types.Command] primitive, whi
graph.invoke(Command(resume={"age": "25"}), thread_config)
```
### Resume multiple interrupts with one invocation
## Resuming Multiple interrupts
If you have multiple interrupts in the task queue, you can use `Command.resume` with a dictionary mapping of interrupt ids to resume with a single `invoke` / `stream` call.
When nodes with interrupt conditions are run in parallel, it's possible to have multiple interrupts in the task queue.
For example, the following graph has two nodes run in parallel that require human input:
<figure markdown="1">
![image](../assets/human_in_loop_parallel.png){: style="max-height:400px"}
</figure>
Once your graph has been interrupted and is stalled, you can resume all the interrupts at once with `Command.resume`, passing a dictionary mapping of interrupt ids to resume values.
For example, once your graph has been interrupted (multiple times, theoretically) and is stalled:
```python
resume_map = {
i.id: f"human input for prompt {i.value}"
for i in parent.get_state(thread_config).interrupts
}
from typing import TypedDict
import uuid
from langchain_core.runnables import RunnableConfig
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.constants import START
from langgraph.graph import StateGraph
from langgraph.types import interrupt, Command
parent_graph.invoke(Command(resume=resume_map), config=thread_config)
class State(TypedDict):
text_1: str
text_2: str
def human_node_1(state: State):
value = interrupt({"text_to_revise": state["text_1"]})
return {"text_1": value}
def human_node_2(state: State):
value = interrupt({"text_to_revise": state["text_2"]})
return {"text_2": value}
graph_builder = StateGraph(State)
graph_builder.add_node("human_node_1", human_node_1)
graph_builder.add_node("human_node_2", human_node_2)
# Add both nodes in parallel from START
graph_builder.add_edge(START, "human_node_1")
graph_builder.add_edge(START, "human_node_2")
checkpointer = InMemorySaver()
graph = graph_builder.compile(checkpointer=checkpointer)
thread_id = str(uuid.uuid4())
config: RunnableConfig = {"configurable": {"thread_id": thread_id}}
result = graph.invoke(
{"text_1": "original text 1", "text_2": "original text 2"}, config=config
)
# Resume with mapping of interrupt IDs to values
resume_map = {
i.id: f"edited text for {i.value['text_to_revise']}"
for i in result["__interrupt__"]
}
print(graph.invoke(Command(resume=resume_map), config=config))
# > {'text_1': 'edited text for original text 1', 'text_2': 'edited text for original text 2'}
```
## Common patterns
@@ -1027,7 +1075,7 @@ def node_in_parent_graph(state: State):
{'parent_node': {'state_counter': 1}}
```
### Using multiple interrupts
### Using multiple interrupts in a single node
Using multiple interrupts within a **single** node can be helpful for patterns like [validating human input](#validate-human-input). However, using multiple interrupts in the same node can lead to unexpected behavior if not handled carefully.